20分特判,一个puts("1")一个快速幂,不讲。
50%算法:
上次就讲了,可是应该还是有像 xuefen某 或 Dybal某 一样没听的。
用a×inv(b)%mod来表示分数的时候,这个分数值可加可乘(有空证明)
像是一个dp题啊。
初状态是1方案数为1,然后做乘法转移不就好了嘛?
设dp[i][j]表示进行了i次操作后所得的值为j
dp[i][j*a[k]%mod]+=dp[i-1][j];
复杂度O(mod2×m)
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<queue> 6 #include<vector> 7 #include<string> 8 #include<cstring> 9 #define int long long 10 #define m(a) memset(a,0,sizeof(a)) 11 #define AA cout<<"Alita"<<endl 12 using namespace std; 13 const int mod=1e9+7; 14 int ans,S,n,m,p,v[1050],a[100500],f[1050][1050],g[1050][1050],tmp[1050][1050]; 15 int poww(int x,int y,int z) 16 { 17 int sum=1; 18 while(y) 19 { 20 if(y&1) sum=sum*x%z; 21 y>>=1; 22 x=x*x%z; 23 } 24 return sum; 25 } 26 void X_g() 27 { 28 memset(tmp,0,sizeof(tmp)); 29 for(int i=1;i<p;i++) 30 { 31 for(int j=1;j<p;j++) 32 { 33 (tmp[1][i]+=g[1][j]*f[j][i]%mod)%=mod; 34 } 35 } 36 for(int i=1;i<p;i++) 37 { 38 g[1][i]=tmp[1][i]; 39 } 40 } 41 void X_f() 42 { 43 memset(tmp,0,sizeof(tmp)); 44 for(int i=1;i<p;i++) 45 { 46 for(int j=1;j<p;j++) 47 { 48 for(int k=1;k<p;k++) 49 { 50 (tmp[i][j]+=f[i][k]*f[k][j]%mod)%=mod; 51 } 52 } 53 } 54 for(int i=1;i<p;i++) 55 { 56 for(int j=1;j<p;j++) 57 { 58 f[i][j]=tmp[i][j]; 59 } 60 } 61 } 62 void work(int y) 63 { 64 while(y) 65 { 66 if(y&1) X_g(); 67 y>>=1; 68 X_f(); 69 } 70 } 71 signed main() 72 { 73 //freopen("1.in","r",stdin); 74 //freopen("1.out","w",stdout); 75 scanf("%lld%lld%lld",&n,&m,&p); 76 if(p==2){puts("1");return 0;} 77 for(int i=1;i<=n;i++) scanf("%lld",&a[i]); 78 if(n==1){printf("%lld",poww(a[1],m,p));return 0;} 79 S=poww(n,mod-2,mod); 80 for(int i=1;i<=n;i++) 81 { 82 (v[a[i]%p]+=S)%=mod; 83 } 84 g[1][1]=1; 85 for(int j=1;j<p;j++) 86 { 87 for(int k=1;k<p;k++) 88 { 89 f[j][j*k%p]+=v[k]; 90 } 91 } 92 work(m); 93 for(int i=1;i<p;i++) 94 { 95 (ans+=g[1][i]*i%mod)%=mod; 96 } 97 printf("%lld",ans); 98 return 0; 99 }