vijosP1049 送给圣诞夜的礼品

 

链接:https://vijos.org/p/1049

 

【思路】

  快速幂+矩阵转换。

  将m次矩阵的转换看作是一次快速幂中的乘法操作,这样可以用O(log(k/m))的时间求出矩阵进行k/m次操作后的结果,然后把剩下的k%m次矩阵转换补上即可。

 

【代码】

 

 

 1 #include<iostream>
 2 #include<cstring>
 3 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
 4 using namespace std;
 5 
 6 const int maxn = 100+10;
 7 
 8 int op[11][maxn];
 9 int _hash[maxn],tmp[maxn],tmp2[maxn],ans[maxn];
10 int n,m,k;
11 
12 void calc(int*A,int*B) { //据B操作改变A 
13     FOR(i,1,n) tmp2[i]=A[B[i]];
14     FOR(i,1,n) A[i]=tmp2[i];
15 }
16 
17 int main() {
18     ios::sync_with_stdio(false);
19     cin>>n>>m>>k;
20     FOR(i,1,m) FOR(j,1,n) cin>>op[i][j];
21     
22     FOR(i,1,n) _hash[i]=ans[i]=i;    //init
23     
24     FOR(i,1,m)  calc(_hash,op[i]);   //calc_hash
25      
26     int T=k/m; k %= m;
27     
28     memcpy(&tmp,&_hash,sizeof(_hash)); //tmp=1
29     while(T) {
30         if(T&1) calc(ans,tmp);      //ans*=tmp
31         calc(tmp,tmp);              //tmp*=tmp
32         T>>=1;
33     }
34     FOR(i,1,k) calc(ans,op[i]);
35     
36     FOR(i,1,n) cout<<ans[i]<<" ";
37     return 0;
38 }