题目链接:点我
题意:
给定一列数,每个数对应一个变换,变换为原先数列一些位置相加起来的和,问r次变换后的序列是多少.
思路:
矩阵快速幂,将需要变换的位置变为1, 其他的都为0, 然后快速幂跑R次即可.
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| #include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<cmath> using namespace std;
const int mod = 1000; int b[100]; int n,r;
struct mat{ int a[52][52]; mat(){memset(a, 0, sizeof(a));} mat operator *(const mat q){ mat c; for(int i = 1; i <= n; ++i) for(int j = 1; j <= n; ++j) if(a[i][j]) for(int k = 1; k <= n; ++k){ c.a[i][k] += a[i][j] * q.a[j][k]; if(c.a[i][k] >= mod) c.a[i][k] %= mod; }return c; } };
mat qpow(mat x, int n){ mat ans; for(int i = 1; i <= 50; ++i) ans.a[i][i] = 1; while(n){ if(n&1) ans = ans * x; x = x * x; n >>= 1; }return ans; }
int main(){ int t; scanf("%d", &t); while(t--){ scanf("%d %d", &n, &r); for(int i = 1; i <= n; ++i) scanf("%d", &b[i]); mat ans; for(int i = 1; i <= n; ++i){ int num; scanf("%d", &num); while(num--){ int k; scanf("%d", &k); ans.a[i][k+1] = 1; } }ans = qpow(ans,r); for(int i = 1; i <= n;++i){ int sum = 0; for(int j = 1; j <= n; ++j){ sum += b[j] * ans.a[i][j]; if(sum>= mod) sum %= mod; } if(i!=n) printf("%d ",sum); else printf("%d\n",sum); } }return 0; }
|