给n个数,r次操作,算出n个数最后的值。
样例分析:1 2 是两个值,2 0 1表示第一个数由来是有两个操作,就是由下标为0,1(即所给的初始值1 2)求和构成,同理1 1表示第二个数由来是有一个操作,即由下标为1(即所给的初始值2)构成,然后得出的值作为下一次操作的初始值继续操作。
可转为矩阵进行求r次快速幂再和初始矩阵乘积即可。样例1就为:
==》
==>求解
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int mod=1000;
int N;
struct matrix{
int x[55][55];
};
matrix ans,shu;
matrix multi(matrix a,matrix b){
matrix tmp;
memset(tmp.x,0,sizeof(tmp.x));
for(int i=1;i<=N;i++)
for(int j=1;j<=N;j++)
for(int k=1;k<=N;k++){
tmp.x[i][j]=(tmp.x[i][j]+a.x[i][k]*b.x[k][j])%mod;
}
return tmp;
}
matrix quick_multi(matrix a,int n){
matrix t;
for(int i=1;i<=N;i++)
for(int j=1;j<=N;j++)
t.x[i][j]=(i==j);
while(n){
if(n&1)
t=multi(t,a);
a=multi(a,a);
n>>=1;
}
return t;
}
int main(){
int t,n,r;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&r);
N=n;
for(int i=1;i<=n;i++)
scanf("%d",&shu.x[i][1]);
int m,val;
memset(ans.x,0,sizeof(ans.x));
for(int i=1;i<=n;i++){
scanf("%d",&m);
for(int j=1;j<=m;j++){
scanf("%d",&val);
ans.x[i][val+1]=1;
}
}
ans=quick_multi(ans,r);
// for(int i=1;i<=n;i++){
// for(int j=1;j<=n;j++)
// printf("%d ",ans.x[i][j]);
// printf("\n");
// }
ans=multi(ans,shu);
for(int i=1;i<=n;i++)
printf("%d%c",ans.x[i][1],i==n?'\n':' ');
}
return 0;
}