[BalkanOI 2007] Dream
吐槽一下出题人
没事干嘛把第一行和最后一行单独列出来
非要让人在代码里加一个分讨
写题的时候都无语了
中午题面里的描述也是奇奇怪怪
从整除的角度来思考
我们需要记录的东西就是当前乘积的因数
对于是否整除可以使用gcd来判断
然后我们还需要一个辅助数组来记录某个乘积和k的gcd有多少种方案数
然后每次更新的时候根据辅助数组来更新即可
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=200+10;
const int N=1001;
int f[maxn][N],now[N],g[N],a[N],b[200010];
int trans[N][N],c[maxn][10010];
int l,t,n,m,p,mod,cnt;
int main(){
cin>>n>>m>>p>>mod;
for(int i=1;i<=p;i++)if(!(p%i))a[++cnt]=i,b[i]=cnt;
for(int i=1;i<=cnt;i++)
for(int j=1;j<=cnt;j++)
trans[i][j]=b[__gcd((int)((ll)a[i]*a[j]%p),p)];
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)cin>>c[i][j];
for(int i=1;i<=n;i++){
memset(g,0,sizeof(g));
for(int j=1;j<=m;j++)(g[b[__gcd(c[i][j],p)]]+=1)%=mod;
for(int j=1;j<=cnt;j++)now[j]=g[j];
if(1<i&&i<n)
for(int j=1;j<=cnt;j++)
for(int k=1;k<=cnt;k++)
if(j==k)(now[trans[j][k]]+=g[j]*(g[j]-1)%mod)%=mod;
else(now[trans[j][k]]+=g[j]*g[k]%mod)%=mod;
for(int j=1;j<=cnt;j++)
for(int k=1;k<=cnt;k++)
(f[i][trans[j][k]]+=f[i-1][j]*now[k]%mod)%=mod;
}
cout<<f[n][cnt];
}

浙公网安备 33010602011771号