题解:
求轨道数。
$Burnside$引理:轨道数=各置换方法下不动点个数的平均值。
代码:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; int n,sr,sb,sg,m,p; int x[70][70],ans; ll fastpow(ll x,int y) { ll ret = 1; while(y) { if(y&1)ret=ret*x%p; x=x*x%p; y>>=1; } return ret; } int inv(int x) { return fastpow(x,p-2); } bool vis[70]; int sta[70],tl; int dp[25][25][25]; int cal(int a[70]) { memset(vis,0,sizeof(vis)); tl = 0; for(int i=1;i<=n;i++)if(!vis[i]) { int u = i; int cnt = 0; while(!vis[u]) { cnt++; vis[u] = 1; u = a[u]; } sta[++tl] = cnt; } memset(dp,0,sizeof(dp)); dp[0][0][0] = 1; for(int i=1;i<=tl;i++) for(int j=sr;j>=0;j--) for(int k=sb;k>=0;k--) for(int l=sg;l>=0;l--) if(dp[j][k][l]) { if(j+sta[i]<=sr)(dp[j+sta[i]][k][l]+=dp[j][k][l])%=p; if(k+sta[i]<=sb)(dp[j][k+sta[i]][l]+=dp[j][k][l])%=p; if(l+sta[i]<=sg)(dp[j][k][l+sta[i]]+=dp[j][k][l])%=p; } return dp[sr][sb][sg]; } int main() { scanf("%d%d%d%d%d",&sr,&sb,&sg,&m,&p); n = sr+sg+sb; for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) scanf("%d",&x[i][j]); for(int i=1;i<=n;i++) x[0][i]=i; int ans = 0; for(int i=0;i<=m;i++) ans=(ans+cal(x[i]))%p; ans = (ans*inv(m+1))%p; printf("%d ",ans); return 0; }