zoukankan      html  css  js  c++  java
  • Bzoj1004 [HNOI2008]Cards

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

    哇原来burnside引理这么好玩的!棒!赶紧来切道题目~

    我们知道Answer=Σf(i,r,b,g)/(m+1) 其中f(i,r,g,b)表示在第i组置换的不动点个数

    那我们需要用dp来解决一下这个问题:

    f[i-c[x]][j][k]+f[i][j-c[x]][k]+f[i][j][k-c[x]]->f[i][j][k]

    c[x]表示当前置换中第i个循环的长度,显然每个循环的颜色必须相同

    复杂度O(RGBM(R+G+B))


    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    int R,B,G,n,m,P,s[110],w[110],f[21][21][21],ans=0;
    inline int pow(int x,int k,int& s){
        for(;k;x=x*x%P,k>>=1) k&1?s=s*x%P:0;
    }
    int cal(){
        int t=0;
        for(int i=1;i<=n;++i) if(s[i]){
            ++t;
            for(int j=i,k;s[j];j=s[j],s[k]=0) k=j,++w[t];
        }
        memset(f,0,sizeof f); ***f=1;
        for(;t;--t)
            for(int i=R;~i;--i)
                for(int j=G;~j;--j)
                    for(int k=B;~k;--k)
                        f[i][j][k]=((i>=w[t]?f[i-w[t]][j][k]:0)+(j>=w[t]?f[i][j-w[t]][k]:0)+(k>=w[t]?f[i][j][k-w[t]]:0))%P;
        return f[R][G][B];
    }
    int main(){
        scanf("%d%d%d%d%d",&R,&G,&B,&m,&P); n=G+B+R;
        for(int j=1;j<=n;++j) s[j]=j; ans=cal();
        for(int i=1;i<=m;++i){
            for(int j=1;j<=n;++j) scanf("%d",s+i);
            ans=(ans+cal())%P;
        }
        pow(m+1,P-2,ans);
        printf("%d
    ",ans);
    }


  • 相关阅读:
    HDU2059(龟兔赛跑)
    pat 1012 The Best Rank
    pat 1010 Radix
    pat 1007 Maximum Subsequence Sum
    pat 1005 Sign In and Sign Out
    pat 1005 Spell It Right
    pat 1004 Counting Leaves
    1003 Emergency
    第7章 输入/输出系统
    第六章 总线
  • 原文地址:https://www.cnblogs.com/Extended-Ash/p/8449234.html
Copyright © 2011-2022 走看看