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

    题目描述

    小春现在很清闲,面对书桌上的N张牌,他决定给每张染色,目前小春只有3种颜色:红色,蓝色,绿色.他询问Sun有多少种染色方案,Sun很快就给出了答案.

    进一步,小春要求染出Sr张红色,Sb张蓝色,Sg张绿色.他又询问有多少种方案,Sun想了一下,又给出了正确答案. 最后小春发明了M种不同的洗牌法,这里他又问Sun有多少种不同的染色方案.两种染色方法相同当且仅当其中一种可以通过任意的洗牌法(即可以使用多种洗牌法,而每种方法可以使用多次)洗成另一种.

    Sun发现这个问题有点难度,决定交给你,答案可能很大,只要求出答案除以P的余数(P为质数).

    输入输出格式

    输入格式:

    第一行输入 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。

    输出格式:

    不同染法除以P的余数

    输入输出样例

    输入样例#1: 复制
    1 1 1 2 7
    2 3 1
    3 1 2
    
    输出样例#1: 复制
    2
    

    说明

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

    题目大意:给出n张牌,分别染a张红色,b张蓝色,c张绿色(n=a+b+c),给出m个置换,问不同的染色方案。

    红色部分就是告述你这些置换构成置换群

    置换群中的染色方案问题可用polya定理解决。

    只要满足同一循环染同一种色

    因为3种颜色要满足数量限制,不能用polya,但可以用burnside

    所以用三维背包求出在置换$a_j$下不变的元素个数$D(a_j)$

    还要算上不置换,也就是单位置换

    所以总共有$|G|=m+1$种置换,根据burnside引理

    $ans=frac{1}{G}sum_{j=1}^{m+1}D(a_j)$

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<cmath>
      6 using namespace std;
      7 int sr,sb,sg,n,m,p,inv;
      8 int vis[1001],f[101][21][21][21],tot,A[1001],s[1001],ans;
      9 int qpow(int x,int y)
     10 {
     11   int res=1;
     12   while (y)
     13     {
     14       if (y&1) res=res*x%p;
     15       x=x*x%p;
     16       y/=2;
     17     }
     18   return res;
     19 }
     20 int dfs(int x,int cnt)
     21 {
     22   if (vis[x])
     23     return cnt;
     24   vis[x]=1;
     25   return dfs(A[x],cnt+1);
     26 }
     27 int main()
     28 {int i,a,b,c;
     29   cin>>sr>>sb>>sg>>m>>p;
     30   n=sr+sb+sg;
     31   inv=qpow(m+1,p-2);
     32   while (m--)
     33     {
     34       tot=0;
     35       memset(vis,0,sizeof(vis));
     36       for (i=1;i<=n;i++)
     37     scanf("%d",&A[i]);
     38       for (i=1;i<=n;i++)
     39     if (vis[i]==0)
     40       {
     41         s[++tot]=dfs(i,0);
     42       }
     43       memset(f,0,sizeof(f));
     44       f[0][0][0][0]=1;
     45       for (i=1;i<=tot;i++)
     46     {
     47       for (a=0;a<=sr;a++)
     48         {
     49           for (b=0;b<=sb;b++)
     50         {
     51           for (c=0;c<=sg;c++)
     52             {
     53               if (a>=s[i])
     54             {
     55               f[i][a][b][c]+=f[i-1][a-s[i]][b][c];
     56               if (f[i][a][b][c]>=p) f[i][a][b][c]-=p;
     57             }
     58               if (b>=s[i])
     59             {
     60               f[i][a][b][c]+=f[i-1][a][b-s[i]][c],f[i][a][b][c]%=p;
     61               if (f[i][a][b][c]>=p) f[i][a][b][c]-=p;
     62             }
     63               if (c>=s[i])
     64             {
     65               f[i][a][b][c]+=f[i-1][a][b][c-s[i]];
     66               if (f[i][a][b][c]>=p) f[i][a][b][c]-=p;
     67             }
     68             }
     69         }
     70         }      
     71     }
     72       ans+=f[tot][sr][sb][sg];
     73       if (ans>=p) ans-=p;
     74     }
     75   memset(f,0,sizeof(f));f[0][0][0][0]=1;
     76   for (i=1;i<=n;i++)
     77     {
     78       for (a=0;a<=sr;a++)
     79     {
     80       for (b=0;b<=sb;b++)
     81         {
     82           for (c=0;c<=sg;c++)
     83         {
     84           if (a>=1)
     85             {
     86               f[i][a][b][c]+=f[i-1][a-1][b][c];
     87               if (f[i][a][b][c]>=p) f[i][a][b][c]-=p;
     88             }
     89           if (b>=1)
     90             {
     91               f[i][a][b][c]+=f[i-1][a][b-1][c],f[i][a][b][c]%=p;
     92               if (f[i][a][b][c]>=p) f[i][a][b][c]-=p;
     93             }
     94           if (c>=1)
     95             {
     96               f[i][a][b][c]+=f[i-1][a][b][c-1];
     97               if (f[i][a][b][c]>=p) f[i][a][b][c]-=p;
     98             }
     99         }
    100         }
    101     }
    102     }
    103   ans+=f[n][sr][sb][sg];
    104   if (ans>=p) ans-=p;
    105   cout<<ans*inv%p;
    106 }
  • 相关阅读:
    20145221 《Java程序设计》第五周学习总结
    Atom插件安装
    Atom使用心得
    20145221 《Java程序设计》第四周学习总结
    20145221 《Java程序设计》第三周学习总结
    20145221 《Java程序设计》第二周学习总结
    20145221 《Java程序设计》第一周学习总结
    调查问卷
    《Java程序设计》第四章-认识对象
    在WEB-INF目录下的web.xml文件
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7709770.html
Copyright © 2011-2022 走看看