POJChallengeRound2 Guideposts 【单位根反演】【快速幂】

题目分析:

这题的目标是求$$ 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 }

 

原文地址:https://www.cnblogs.com/Menhera/p/10394970.html