zoukankan      html  css  js  c++  java
  • [bzoj1004][HNOI2008]Cards【群论】

    【题目链接】
      http://www.lydsy.com/JudgeOnline/problem.php?id=1004
    【题解】
      由于数量有限制,无法使用Polya定理,要用Burnside引理。即ans=
      对于每种置换,我们可以用dp来统计答案。记f[i][j][k]表示已经处理了i个位置,第1种颜色用了j个,第2种颜色用了k个。每次处理一个新的循环。分别用i,j,k取填这个循环。设当前循环长度为t,有f[i][j][k]=f[it][jt][k]+f[it][j][kt]+f[it][j][k]。注意负数不合法。
      

    /* --------------
        user Vanisher
        problem bzoj-1004 
    ----------------*/
    # include <bits/stdc++.h>
    # define    ll      long long
    # define    inf     0x3f3f3f3f
    # define    N       110
    using namespace std;
    int read(){
        int tmp=0, fh=1; char ch=getchar();
        while (ch<'0'||ch>'9'){if (ch=='-') fh=-1; ch=getchar();}
        while (ch>='0'&&ch<='9'){tmp=tmp*10+ch-'0'; ch=getchar();}
        return tmp*fh;
    }
    int f[2][N][N],mp[N],P,sa,sb,sc,m,n,now,use[N],f1,f2;
    int mypow(int x, int y){
        int i=x; x=1;
        while (y>0){
            if (y%2==1) x=x*i%P;
            i=i*i%P;
            y/=2;
        }
        return x;
    }
    int main(){
        sa=read(), sb=read(), sc=read();
        m=read(); P=read(); n=sa+sb+sc;
        now=0;
        for (int i=1; i<=m+1; i++){
            if (i!=m+1){
            for (int j=1; j<=n; j++)
                mp[j]=read(),use[j]=false;
            }
            else {
                for (int j=1; j<=n; j++)
                    mp[j]=j, use[j]=false;
            }
            int les=0;
            f1=0, f2=1;
            memset(f,0,sizeof(f));
            f[f1][0][0]=1;
            for (int ed=1; ed<=n; ed++){
                if (use[ed]==true) continue;
                int num=0,k=ed;
                while (use[k]==false){
                    use[k]=true;
                    num++, k=mp[k];
                }
                les=les+num;
                for (int j=0; j<=sa; j++)
                    for (int k=0; k<=sb; k++){
                        int t=les-j-k;
                        f[f2][j][k]=0;
                        if (j>=num) f[f2][j][k]=(f[f2][j][k]+f[f1][j-num][k])%P;
                        if (k>=num) f[f2][j][k]=(f[f2][j][k]+f[f1][j][k-num])%P;
                        if (t>=num) f[f2][j][k]=(f[f2][j][k]+f[f1][j][k])%P;
                    }
                swap(f1,f2);
            }
            now=(now+f[f1][sa][sb])%P;
        }
        printf("%d
    ",now*mypow(m+1,P-2)%P);
        return 0;
    }
    
  • 相关阅读:
    php遍历目录下的所有文件夹
    PHP 遍历文件
    PHP中public protected private的区别
    mysql数据库优化的方法
    Thinkphp 验证器
    PHP 接口
    php获取表单的值
    PHP 数组
    php 递归
    [go系列] 函数
  • 原文地址:https://www.cnblogs.com/Vanisher/p/9135983.html
Copyright © 2011-2022 走看看