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

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 3449  Solved: 2067

    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。

    Source

    数学问题 置换群 burnside引理 动规 背包DP

    对于每一种洗牌方式(置换),显然同一个循环节内(即通过该种洗牌方式)只能填同一个颜色。枚举每种置换,统计出其中的循环节大小和尺寸,01背包DP出方案即可。

     1 /*by SilverN*/
     2 #include<algorithm>
     3 #include<iostream>
     4 #include<cstring>
     5 #include<cstdio>
     6 #include<cmath>
     7 #include<vector>
     8 #define LL long long
     9 using namespace std;
    10 const int mxn=105;;
    11 int read(){
    12     int x=0,f=1;char ch=getchar();
    13     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    14     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
    15     return x*f;
    16 }
    17 int sr,sb,sg;
    18 int n,m,p;
    19 LL f[mxn][mxn][mxn];
    20 int a[mxn][mxn];
    21 int sz[mxn],cnt=0;
    22 bool vis[mxn];
    23 LL dp(int x){
    24 //  printf("dpx:%d
    ",x);
    25     int i,j,k,l;
    26     memset(vis,0,sizeof vis);
    27     cnt=0;
    28     for(i=1;i<=n;i++){
    29         if(vis[i])continue;
    30         vis[i]=1;
    31         ++cnt;
    32         sz[cnt]=1;
    33         int t=a[x][i];
    34         while(t!=i){
    35             sz[cnt]++;
    36             vis[t]=1;
    37             t=a[x][t];
    38         }
    39     }
    40     memset(f,0,sizeof f);
    41     f[0][0][0]=1;
    42     for(i=1;i<=cnt;i++){
    43 //      printf("sz:%d
    ",sz[i]);
    44         for(j=sr;j>=0;j--)
    45             for(k=sb;k>=0;k--)
    46                 for(l=sg;l>=0;l--){
    47                     if(j>=sz[i])f[j][k][l]=(f[j][k][l]+f[j-sz[i]][k][l])%p;
    48                     if(k>=sz[i])f[j][k][l]=(f[j][k][l]+f[j][k-sz[i]][l])%p;
    49                     if(l>=sz[i])f[j][k][l]=(f[j][k][l]+f[j][k][l-sz[i]])%p;
    50                 }
    51     }
    52 //  printf("res%d:%lld
    ",x,f[sr][sb][sg]);
    53     return f[sr][sb][sg];
    54 }
    55 LL ans=0;
    56 LL ksm(LL a,LL k){
    57     LL res=1;
    58     while(k){
    59         if(k&1)res=res*a%p;
    60         a=a*a%p;
    61         k>>=1;
    62     }
    63     return res;
    64 }
    65 int main(){
    66     int i,j;
    67     sr=read();sb=read();sg=read();m=read();p=read();
    68     n=sr+sb+sg;
    69     for(i=1;i<=m;i++)
    70         for(j=1;j<=n;j++)
    71             a[i][j]=read();
    72     m++;
    73     for(i=1;i<=n;i++)a[m][i]=i;
    74     LL inv=ksm(m,p-2);
    75     for(i=1;i<=m;i++)
    76         ans=ans+dp(i);
    77 //  printf("ans:%lld inv:%lld
    ",ans,inv);
    78     ans=ans*inv%p;
    79     printf("%lld
    ",ans);
    80     return 0;
    81 }
    82 
  • 相关阅读:
    CDH环境搭建及部署
    Window 安装Sqoop 环境
    软件——keil的查找,错误,不能跳转到相应的行
    软件——机器学习与Python,输入输出的用法
    软件——机器学习与Python,聚类,K——means
    软件——机器学习与Python,if __name__ == '__main__':函数
    硬件——STM32,ADC篇
    生活的开始
    硬件——nrf51822第三篇,按键控制小灯
    硬件——nrf51822第二篇,如何设置keil用来下载程序
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6697573.html
Copyright © 2011-2022 走看看