题目分析:
这题的目标是求$$ sum_{i in [0,n),k mid i} inom{n}{i}G^i $$
这个形式很像单位根反演。
单位根反演一般用于求:$ sum_{i in [0,n),k mid i} inom{n}{i}f(x)^i $
推理过程略,实际上也就是交换求和符号的事情。
接着就变成裸的矩阵快速幂了
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 int m,k,p;long long n; 5 int l,s,t,gg; 6 7 struct mat{int arr[7][7];}G,bs,mmp; 8 vector<int> fac; // factor of p 9 10 void buildbase(int w){ 11 for(int i=1;i<=m;i++) 12 for(int j=1;j<=m;j++) bs.arr[i][j] = 1ll*w*G.arr[i][j]%p; 13 for(int i=1;i<=m;i++) bs.arr[i][i] ++,bs.arr[i][i] %= p; 14 } 15 16 mat operator*(mat alpha,mat beta){ 17 memset(mmp.arr,0,sizeof(mmp.arr)); 18 for(int k=1;k<=m;k++){ 19 for(int i=1;i<=m;i++){ 20 for(int j=1;j<=m;j++){ 21 mmp.arr[i][j] += 1ll*alpha.arr[i][k]*beta.arr[k][j]%p; 22 mmp.arr[i][j] %= p; 23 } 24 } 25 } 26 return mmp; 27 } 28 29 mat res; 30 mat fstpow(mat now,long long pw){ 31 memset(res.arr,0,sizeof(res.arr)); 32 for(int i=1;i<=m;i++) res.arr[i][i] = 1; 33 long long bit = 1; 34 while(bit <= pw){ 35 if(bit & pw){res = res*bs;} 36 bs = bs*bs;bit<<=1; 37 } 38 return res; 39 } 40 41 void init(){ 42 memset(G.arr,0,sizeof(G.arr)); 43 fac.clear(); 44 l = s = t = gg = 0; 45 } 46 47 void read(){ 48 scanf("%d%d%d",&l,&s,&t); 49 for(int i=1;i<=l;i++){ 50 int u,v; scanf("%d%d",&u,&v); 51 G.arr[u][v]++; 52 } 53 } 54 55 int fast_pow(int now,int pw){ 56 int ans = 1,dt = now,bit = 1; 57 while(bit <= pw){ 58 if(bit & pw){ans = 1ll*ans*dt%p;} 59 dt = 1ll*dt*dt%p; bit<<=1; 60 } 61 return ans; 62 } 63 64 void getgg(){ 65 int z = p-1; 66 for(int i=2;i*i<=z;i++){ 67 if(z % i == 0){ 68 fac.push_back(i); 69 while(z % i == 0) z /= i; 70 } 71 } 72 if(z != 1) fac.push_back(z); 73 for(int i=2;i<=p;i++){ 74 int flag = true; 75 for(int j=0;j<fac.size();j++){ 76 int z = fast_pow(i,(p-1)/fac[j]); 77 if(z == 1){flag = false; break;} 78 } 79 if(flag){gg = i;break;} 80 } 81 gg = fast_pow(gg,(p-1)/k); 82 } 83 84 void work(){ 85 int w = 1,ans = 0; 86 for(int i=0;i<k;i++,w = 1ll*w*gg%p){ 87 buildbase(w); 88 bs = fstpow(bs,n); 89 ans += bs.arr[s][t]; ans%=p; 90 } 91 ans = 1ll*ans*fast_pow(k,p-2)%p; 92 printf("%d ",ans); 93 } 94 95 int main(){ 96 while(scanf("%d%lld%d%d",&m,&n,&k,&p) == 4){ 97 init(); 98 read(); 99 getgg(); 100 work(); 101 } 102 return 0; 103 }