正题
题目链接:https://www.luogu.com.cn/problem/P1446
题目大意
三个颜色的一些东西排在一起,给mmm种置换,求本质不同的染色方案数。
解题思路
BurnsideBurnsideBurnside引理:置换集合GGG时本质不同的序列方案等于∑x∈Gc(x)∣G∣\frac{\sum_{x\in G}c(x)}{|G|}∣G∣∑x∈Gc(x),c(x)c(x)c(x)表示置换xxx中的不动点个数。
也就是每个循环中的颜色都相同,可以把每个循环视为一个物品,然后放入容量为r,g,br,g,br,g,b的背包里的方案数,求解即可。
时间复杂度O(r∗g∗b∗m)O(r*g*b*m)O(r∗g∗b∗m)
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
ll r,b,g,m,p,n,tot,ans;
ll siz[81],f[21][21][21],y[81];
bool v[81];
ll power(ll x,ll b){ll ans=1;while(b){if(b&1)ans=ans*x%p;x=x*x%p;b>>=1;}return ans;
}
ll solve(){memset(f,0,sizeof(f));memset(v,0,sizeof(v));tot=0;for(ll i=1;i<=n;i++){if(v[i])continue;siz[++tot]=0;ll x=i;while(!v[x]){siz[tot]++;v[x]=1;x=y[x];}}f[0][0][0]=1;for(ll x=1;x<=tot;x++)for(ll i=r;i>=0;i--)for(ll j=g;j>=0;j--)for(ll k=b;k>=0;k--){if(i>=siz[x])(f[i][j][k]+=f[i-siz[x]][j][k])%=p;if(j>=siz[x])(f[i][j][k]+=f[i][j-siz[x]][k])%=p;if(k>=siz[x])(f[i][j][k]+=f[i][j][k-siz[x]])%=p;}return f[r][g][b];
}
int main()
{scanf("%lld%lld%lld%lld%lld",&r,&g,&b,&m,&p);n=r+b+g;for(ll i=1;i<=n;i++)y[i]=i;ans=solve();for(ll i=1;i<=m;i++){for(ll j=1;j<=n;j++)scanf("%lld",&y[j]);(ans+=solve())%=p;}printf("%lld\n",ans*power(m+1,p-2)%p);return 0;
}