UVA11551 Experienced Endeavour —— 矩阵快速幂
题目链接:https://vjudge.net/problem/UVA-11551
题意:
给定一列数,每个数对应一个变换,变换为原先数列一些位置相加起来的和,问r次变换后的序列是多少
题解:
构造矩阵:要加的位置值为1,其余位置为0。然后用快速幂计算。
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 #include <cmath> 7 #include <queue> 8 #include <stack> 9 #include <map> 10 #include <string> 11 #include <set> 12 using namespace std; 13 typedef long long LL; 14 const int INF = 2e9; 15 const LL LNF = 9e18; 16 //const int MOD = 1000000007; 17 const int MAXN = 1e6+100; 18 19 const int MOD = 1000; 20 const int Size = 50; 21 struct MA 22 { 23 LL mat[Size][Size]; 24 void init() 25 { 26 for(int i = 0; i<Size; i++) 27 for(int j = 0; j<Size; j++) 28 mat[i][j] = (i==j); 29 } 30 }; 31 32 MA mul(MA x, MA y) 33 { 34 MA ret; 35 memset(ret.mat, 0, sizeof(ret.mat)); 36 for(int i = 0; i<Size; i++) 37 for(int j = 0; j<Size; j++) 38 for(int k = 0; k<Size; k++) 39 ret.mat[i][j] += (1LL*x.mat[i][k]*y.mat[k][j])%MOD, ret.mat[i][j] %= MOD; 40 return ret; 41 } 42 43 MA qpow(MA x, LL y) 44 { 45 MA s; 46 s.init(); 47 while(y) 48 { 49 if(y&1) s = mul(s, x); 50 x = mul(x, x); 51 y >>= 1; 52 } 53 return s; 54 } 55 56 int main() 57 { 58 LL T, n, r, a[55]; 59 scanf("%lld", &T); 60 while(T--) 61 { 62 scanf("%lld%lld", &n, &r); 63 for(int i = 0; i<n; i++) 64 scanf("%lld", &a[i]); 65 66 MA s; 67 memset(s.mat, 0, sizeof(s.mat)); 68 for(int i = 0; i<n; i++) 69 { 70 int m, x; 71 scanf("%d", &m); 72 while(m--) 73 { 74 scanf("%d", &x); 75 s.mat[i][x] = 1; 76 } 77 } 78 79 s = qpow(s, r); 80 for(int i = 0; i<n; i++) 81 { 82 LL sum = 0; 83 for(int j = 0; j<n; j++) 84 sum += s.mat[i][j]*a[j], sum %= MOD; 85 printf("%lld", sum); 86 if(i!=n-1) printf(" "); 87 } 88 printf("\n"); 89 } 90 }