传送门
解析:
很显然, t t t轮之后点 i i i对点 j j j产生贡献的比例是可以用矩阵乘法算出的。
计算出转移矩阵之后只需要用一个 1 × n 1\times n 1×n的原始状态矩阵乘上去就行了,所以现在考虑怎么优化求出转移矩阵的时间复杂度。
一种想法是二进制拆分,但是复杂度还有一个 log \log log感觉不是很卡得过去。。。
另外一种想法就是利用BSGS。
但是我们发现分 n \sqrt n n块空间卡不过去。。。
那么就分成四份,按照 n 4 \sqrt[4]n 4n来算就行了。但是我为了方便,直接用的256块一步。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define gc get_char
#define cs const
namespace IO{
inline char get_char(){
static cs int Rlen=1<<20|1;
static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
inline int getint(){
re char c;
while(!isdigit(c=gc()));re int num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}
}
using namespace IO;
using std::cout;
using std::cerr;
using std::swap;
cs int mod=998244353;
inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(int a,int b){return a<b?a-b+mod:a-b;}
inline int mul(int a,int b){return (ll)a*b%mod;}
inline int quickpow(int a,int b,int res=1){
while(b){
if(b&1)res=mul(res,a);
a=mul(a,a);
b>>=1;
}
return res;
}
cs int SIZE=50,N=50;
struct matrix{
int a[SIZE][SIZE];
int r,c;
matrix(){memset(a,0,sizeof a);}
int *operator[](int offset){return a[offset];}
cs int *operator[](int offset)cs{return a[offset];}
friend matrix operator*(cs matrix &A,cs matrix &B){
matrix C;C.r=A.r,C.c=B.c;
for(int re i=0;i<A.r;++i)
for(int re j=0;j<A.c;++j)if(A[i][j])
for(int re k=0;k<B.c;++k)C[i][k]=add(C[i][k],mul(A[i][j],B[j][k]));
return C;
}
}A0[256],A1[256],A2[256],A3[256],ori,res;
int n,m,q,deg[N],inv[(N+1)*N];
inline void init(){
n=getint();m=getint();q=getint();
inv[0]=inv[1]=1;
for(int re i=2;i<N*(N+1);++i)inv[i]=mul(inv[mod%i],mod-mod/i);
for(int re i=0;i<n;++i)ori[0][i]=getint(),A0[0][i][i]=deg[i]=1;
ori.r=1,ori.c=A0[0].r=A0[0].c=n;
A0[1]=A0[0];
while(m--){
int x=getint()-1,y=getint()-1;
++A0[1][x][y];
++deg[x];
}
for(int re i=0;i<n;++i)
for(int re j=0;j<n;++j)A0[1][i][j]=mul(A0[1][i][j],inv[deg[i]]);
for(int re i=2;i<256;++i)A0[i]=A0[i-1]*A0[1];
A1[0]=A0[0],A1[1]=A0[255]*A0[1];
for(int re i=2;i<256;++i)A1[i]=A1[i-1]*A1[1];
A2[0]=A1[0],A2[1]=A1[255]*A1[1];
for(int re i=2;i<256;++i)A2[i]=A2[i-1]*A2[1];
A3[0]=A2[0],A3[1]=A2[255]*A2[1];
for(int re i=2;i<256;++i)A3[i]=A3[i-1]*A3[1];
}
signed main(){
init();
std::ios::sync_with_stdio(false);
while(q--){
m=getint();
res=ori*A0[m&255]*A1[m>>8&255]*A2[m>>16&255]*A3[m>>24&255];
int ans=0;
for(int re i=0;i<n;++i)ans^=res[0][i];
cout<<ans%mod<<"\n";
}
return 0;
}