zoukankan      html  css  js  c++  java
  • 【洛谷1446】[HNOI2008] Cards(Burnside引理+简单背包)

    点此看题面

    • 要求将(n)张牌染成红、蓝、绿三色,每种颜色牌数分别为(S_r,S_b,S_g)
    • 给定(m)种洗牌方式,保证加上原置换之后形成一个置换群,求有多少种本质不同的染色方案。
    • (S_r,S_b,S_gle20,mle60)

    (Burnside)引理

    给定颜色数目是无法(Polya)定理的,因此我们考虑(Burnside)引理:

    [L=frac1{|G|}sum_{j=1}^sD(a_j) ]

    对于一个置换(p),我们可以把它分成若干个环,那么想让一种染色方案在该置换下不变,就是要让每个环的颜色相同。

    我们可以通过一个简单背包求解,即设(f_{i,j,k})表示处理到第(i)个环,有(j)张红牌和(k)张蓝牌的方案数,那么(D(p))就等于(f_{n,S_r,S_b})

    代码:(O(nmS^2))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define S 20
    #define Inc(x,y) ((x+=(y))>=X&&(x-=X))
    using namespace std;
    int n,m,s1,s2,s3,ans,X,p[3*S+5];
    I int QP(RI x,RI y) {RI t=1;W(y) y&1&&(t=1LL*t*x%X),x=1LL*x*x%X,y>>=1;return t;} 
    int c[3*S+5],vis[3*S+5],f[3*S+5][S+5][S+5];I void DP()//简单背包
    {
    	RI i,j,k,t=0;for(i=1;i<=n;++i) if(!vis[i]) {++t,j=i;W(!vis[j]) ++c[t],vis[j]=1,j=p[j];}//分成若干个环
    	for(i=0;i<=t;++i) for(j=0;j<=s1;++j) for(k=0;k<=s2;++k) f[i][j][k]=0;f[0][0][0]=1;//初始化DP数组
    	for(i=1;i<=t;++i) for(j=0;j<=s1;++j) for(k=0;k<=s2;++k) Inc(f[i][j][k],f[i-1][j][k]),//填绿色
    		j+c[i]<=s1&&Inc(f[i][j+c[i]][k],f[i-1][j][k]),k+c[i]<=s2&&Inc(f[i][j][k+c[i]],f[i-1][j][k]);//填红色;填蓝色
    	for(Inc(ans,f[t][s1][s2]),i=1;i<=n;++i) c[i]=vis[i]=0;//统计答案后清空
    }
    int main()
    {
    	RI i,j;for(scanf("%d%d%d%d%d",&s1,&s2,&s3,&m,&X),n=s1+s2+s3,i=1;i<=n;++i) p[i]=i;DP();//原置换
    	for(i=1;i<=m;++i) {for(j=1;j<=n;++j) scanf("%d",p+j);DP();}return printf("%d
    ",1LL*ans*QP(m+1,X-2)%X),0;//统计所有置换下不变方案数,除以置换总数m+1
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    docker 部署 zabbix
    docker 搭建私有云仓库
    doeker部署zabbix
    LVS
    zabbix安装与配置
    keepalive
    Shell编程(5)
    Shell编程(4)
    Shell编程(3)
    几种Toast用法
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu1446.html
Copyright © 2011-2022 走看看