• 【BZOJ1004】Cards(组合数学,Burnside引理)


    【BZOJ1004】Cards(组合数学,Burnside引理)

    题面

    Description

      小春现在很清闲,面对书桌上的N张牌,他决定给每张染色,目前小春只有3种颜色:红色,蓝色,绿色.他询问Sun有
    多少种染色方案,Sun很快就给出了答案.进一步,小春要求染出Sr张红色,Sb张蓝色,Sg张绝色.他又询问有多少种方
    案,Sun想了一下,又给出了正确答案. 最后小春发明了M种不同的洗牌法,这里他又问Sun有多少种不同的染色方案.
    两种染色方法相同当且仅当其中一种可以通过任意的洗牌法(即可以使用多种洗牌法,而每种方法可以使用多次)洗
    成另一种.Sun发现这个问题有点难度,决定交给你,答案可能很大,只要求出答案除以P的余数(P为质数).

    Input

      第一行输入 5 个整数:Sr,Sb,Sg,m,p(m<=60,m+1<p<100)。n=Sr+Sb+Sg。
    接下来 m 行,每行描述一种洗牌法,每行有 n 个用空格隔开的整数 X1X2...Xn,恰为 1 到 n 的一个排列,
    表示使用这种洗牌法,第 i位变为原来的 Xi位的牌。输入数据保证任意多次洗牌都可用这 m种洗牌法中的一种代
    替,且对每种洗牌法,都存在一种洗牌法使得能回到原状态。

    Output

      不同染法除以P的余数

    Sample Input

    1 1 1 2 7

    2 3 1

    3 1 2

    Sample Output

    2

    HINT

      有2 种本质上不同的染色法RGB 和RBG,使用洗牌法231 一次可得GBR 和BGR,使用洗牌法312 一次 可得BRG

    和GRB。

    100%数据满足 Max{Sr,Sb,Sg}<=20。

    题解

    Burnside引理:
    对于一个置换群
    等价类的个数,等于所有置换的不动点的平均数

    所以,这道题目相当于有(m+1)个置换
    求总的不动点个数
    其中,置换包括不变和题目给定的(m)

    然后是求不动点的个数的问题
    每一个置换相当于若干个循环
    如果是不动点的话,
    循环中的每个点的颜色应当相同
    于是大力跑一个01背包就好了

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    #define MAX 100
    #define MOD P
    inline int read()
    {
        int x=0,t=1;char ch=getchar();
        while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
        if(ch=='-')t=-1,ch=getchar();
        while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
        return x*t;
    }
    int s1,s2,s3,m,P,n,ans;
    int a[MAX][MAX],size[MAX];
    int f[MAX][MAX][MAX];
    bool vis[MAX];
    int fpow(int a,int b)
    {
        int s=1;
        while(b){if(b&1)s=1ll*s*a%P;a=1ll*a*a%P;b>>=1;}
        return s;
    }
    int DP(int x)//求关于第x置换的不动点的个数
    {
        memset(size,0,sizeof(size));
        memset(vis,0,sizeof(vis));
        int sum=0;//拆成循环
        for(int i=1;i<=n;++i)
            if(!vis[i])
            {
                size[++sum]=1;vis[i]=true;
                int p=i;
                while(!vis[a[x][p]])size[sum]++,vis[p=a[x][p]]=true;
            }
        memset(f,0,sizeof(f));
        f[0][0][0]=1;
        for(int t=1;t<=sum;++t)
            for(int i=s1;i>=0;--i)
                for(int j=s2;j>=0;--j)
                    for(int k=s3;k>=0;--k)
                    {
                        if(i>=size[t])f[i][j][k]=(f[i][j][k]+f[i-size[t]][j][k])%MOD;
                        if(j>=size[t])f[i][j][k]=(f[i][j][k]+f[i][j-size[t]][k])%MOD;
                        if(k>=size[t])f[i][j][k]=(f[i][j][k]+f[i][j][k-size[t]])%MOD;
                    }
        return f[s1][s2][s3];
    }
    int main()
    {
        s1=read();s2=read();s3=read();m=read();P=read();
        n=s1+s2+s3;
        for(int i=1;i<=m;++i)
            for(int j=1;j<=n;++j)
                a[i][j]=read();
        ++m;
        for(int i=1;i<=n;++i)a[m][i]=i;//不动也是一种置换
        for(int i=1;i<=m;++i)
            ans=(ans+DP(i))%MOD;
        printf("%lld
    ",1ll*ans*fpow(m,P-2)%P);
        return 0;
    }
    
    
  • 相关阅读:
    老陈与小石头运算代码
    第五次作业
    老陈与小石头
    简易四则运算
    四则运算
    对git的认识
    第一次作业
    arcgis-tomcat-cors
    jquery deferred promise
    springloaded hot deploy
  • 原文地址:https://www.cnblogs.com/cjyyb/p/8158795.html
Copyright © 2020-2023  润新知