zoukankan      html  css  js  c++  java
  • bzoj1004 Cards

    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种洗牌法中的一种代替,且对每种
    洗牌法,都存在一种洗牌法使得能回到原状态。

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

    Output

    不同染法除以P的余数

    Sample Input

    1 1 1 2 7
    2 3 1
    3 1 2

    Sample Output

    2
     
    根据burnside引理,我们可以知道,L=(1/G)*Σd(gi)
    根据polay计数,可以转变为L=(1/G)*(每个置换里面的不变染色方案数)
    但是这题三种颜色都有数量限制,因此,我们用dp运算每个置换里面不变的染色方案数。
    还有一点,就是每个位置i上都放i也是一种置换,不要忘记加上这个置换的答案
    最后乘以(m+1)在p下逆元即是答案。
     1 #include<algorithm>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<iostream>
     6 int f[25][25][25];
     7 int n,b[105],st[105],id[105],sum[105],inv[205],m,p,sr,sb,sg,sz,g[205];
     8 int dp(){
     9     sz=0;
    10     for (int i=1;i<=n;i++) b[i]=0;
    11     for (int i=0;i<=n;i++) st[i]=id[i]=sum[i]=0;
    12     sum[0]=0;
    13     for (int i=1;i<=n;i++) 
    14      if (!b[i]){
    15         int ans=0;
    16         while (!b[g[i]]) i=g[i],b[i]=1,ans++;
    17         st[++sz]=ans;sum[sz]=sum[sz-1]+ans;id[sum[sz]]=sz;
    18      }
    19     for (int i=0;i<=sr;i++)
    20      for (int j=0;j<=sb;j++)
    21       for (int k=0;k<=sg;k++) 
    22        f[i][j][k]=0;
    23     f[0][0][0]=1;   
    24     for (int i=0;i<=sr;i++)
    25      for (int j=0;j<=sb;j++)
    26       for (int k=0;k<=sg;k++)
    27         if (id[i+j+k]){
    28             int v=st[id[i+j+k]];
    29             if (i>=v) f[i][j][k]=(f[i][j][k]+f[i-v][j][k])%p;
    30             if (j>=v) f[i][j][k]=(f[i][j][k]+f[i][j-v][k])%p;
    31             if (k>=v) f[i][j][k]=(f[i][j][k]+f[i][j][k-v])%p;
    32         }
    33     return f[sr][sb][sg];    
    34 }
    35 int main(){
    36     scanf("%d%d%d%d%d",&sr,&sb,&sg,&m,&p);
    37     n=sr+sb+sg;
    38     inv[1]=1;
    39     int ans=0;
    40     for (int i=2;i<p;i++)
    41      inv[i]=(((p-p/i)%p)*(inv[p%i]))%p;
    42     inv[p]=1;
    43     for (int i=1;i<=m;i++){
    44         for (int j=1;j<=n;j++)
    45          scanf("%d",&g[j]);
    46         ans=(ans+dp())%p;
    47     } 
    48     for (int i=1;i<=n;i++)
    49      g[i]=i;
    50     ans=(ans+dp())%p;
    51     ans=(ans*inv[m+1])%p;
    52     printf("%d
    ",ans); 
    53 }
  • 相关阅读:
    门头沟PHP,java编程兴趣小组欢迎大家的加入。
    mysql数据库怎么存入emoji表情,更改utf8mb4后为什么出现全是问号
    Laravel发送邮件配置-问题解决
    php版本低更换php版本-问题以解决
    极光客户互动云java post请求
    【问题解决】增加https后 phpcms 分页错误
    阿里云阿里免费ssl wap网站在手机微信、手机浏览器无法访问
    Kali Linux on Android # 实测:小米2s离线安装Kali Linux
    3-1 LVS-NAT集群
    使用LVM方式安装Ubuntu 16.04
  • 原文地址:https://www.cnblogs.com/qzqzgfy/p/5527948.html
Copyright © 2011-2022 走看看