zoukankan      html  css  js  c++  java
  • bzoj 1004

    计数好题

    首先看到这种问题直接想到的应该是polya定理

    可是对颜色使用个数有限制啊!

    没关系,我们分析一下polya定理的表达式:

    $frac{1}{|G|}sum_{i=1}^{n}m^{c_{i}}$

    可以看到,这其中的每一项等价于用$m$种颜色对每个循环节任意染色的方案数(即对每个循环节内的元素染成相同颜色的方案数)

    因此对于这个有限制的问题,我们可以用简单的背包求出这一方案数

    最后对方案数求和,乘个逆元即可

    注意:不要忘了群的基本定义,一个置换群里是需要单位元的,因此需要补充一个原始置换

    代码:

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #define ll long long
    using namespace std;
    ll sr,sb,sg,m,p;
    int to[65];
    bool vis[65];
    int siz[65][65];
    ll f[65][25][25][25];
    int val[65];
    ll pow_mul(ll x,ll y)
    {
        ll ret=1;
        while(y)
        {
            if(y&1)ret=ret*x%p;
            x=x*x%p,y>>=1;
        }
        return ret;
    }
    int main()
    {
        scanf("%lld%lld%lld%lld%lld",&sr,&sb,&sg,&m,&p);
        ll n=sr+sb+sg;
        for(int i=1;i<=m;i++)
        {
            for(int j=1;j<=n;j++)scanf("%d",&to[j]);
            memset(vis,0,sizeof(vis));
            for(int j=1;j<=n;j++)
            {
                int p=j;
                if(vis[p])continue;
                val[i]++;
                while(!vis[p])
                {
                    siz[i][val[i]]++;
                    vis[p]=1;
                    p=to[p];
                }
            }
        }    
        m++;
        val[m]=n;
        for(int i=1;i<=n;i++)siz[m][i]=1;
        ll s=0;
        for(int t=1;t<=m;t++)//枚举第几个循环 
        {
            ll S=0;
            memset(f,0,sizeof(f));
            f[0][0][0][0]=1;
            for(int i=1;i<=val[t];i++)
            {
                S+=siz[t][i];
                for(int j=0;j<=sr;j++)//枚举红色的个数 
                {
                    for(int k=0;k<=sb;k++)
                    {
                        if(S-j-k>sg)continue;
                        if(j>=siz[t][i])f[i][j][k][S-j-k]+=f[i-1][j-siz[t][i]][k][S-j-k];
                        if(k>=siz[t][i])f[i][j][k][S-j-k]+=f[i-1][j][k-siz[t][i]][S-j-k];
                        if(S-j-k>=siz[t][i])f[i][j][k][S-j-k]+=f[i-1][j][k][S-j-k-siz[t][i]];
                        f[i][j][k][S-j-k]%=p;                
                    }
                }
            }
            s+=f[val[t]][sr][sb][sg];
            s%=p;
        }
        s=s*pow_mul(m,p-2)%p;
        printf("%lld
    ",s);
        return 0;
    }
  • 相关阅读:
    thymeleaf的基本用法
    IK配置远程自定义词典热更新词库
    mysql卸载及安装及修改用户密码登录问题处理win10系统
    js获取table元素中的tr及td的值
    java中日期与字符串的转换
    layui使用动态渲染表单数据
    Tomcat 80端口被占用
    windows和Linux下定时启动或关闭服务
    【UE】常用的UltraEdit使用技巧
    Oracle查询显示CLOB的内容
  • 原文地址:https://www.cnblogs.com/zhangleo/p/11010654.html
Copyright © 2011-2022 走看看