zoukankan      html  css  js  c++  java
  • 【BZOJ1004】【HNOI20008】cards

    看黄学长的代码才写出来的,sro_hzwer_orz

    原题:

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

    m<=60,m+1<p<100,Max{Sr,Sb,Sg}<=20。

    已经把置换给出来了,要么burnside,要么polya,然而这题颜色有使用限制,所以不能用polya(polya还没理解,这里还不懂)

    所以就用burnside:一个置换群的等价计数=(每个置换的置换后等价情况数)/置换总数

    置换后的等价情况数就是在置换中没变的数,这个很好写

    然后在置换中没变的数要刷的颜色是一样的,只有三种颜色所以就可以搞个三维的01包计数

    最后除的内个置换总数因为要膜,所以要用到除法逆元

    怎么用呐:

    bx mod p=1,x就是b模P的乘法逆元,呢么x≡1/b(mod p),呢么a/b≡ax(mod p),然后用扩展欧几里得求乘法逆元即可(就是解bx mod p=1,某年NOIPT1)

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cmath>
     6 using namespace std;
     7 int sr,sb,sg,n,m,p;
     8 int huan[110][110];
     9 bool visited[110];
    10 int ge[110];
    11 int f[110][110][110];
    12 int ans=0;
    13 void exgcd(int a,int b,int &x,int &y){
    14     if(!b){  x=1,y=0;  return ;}
    15     exgcd(b,a%b,x,y);
    16     int t=x;  x=y;  y=t-a/b*y;
    17 }
    18 int dp(int x){
    19     memset(visited,0,sizeof(visited));
    20     int cnt=0,temp;
    21     for(int i=1;i<=n;i++)if(!visited[i]){
    22         visited[i]=true;
    23         ge[++cnt]=1;  temp=i;
    24         while(!visited[huan[x][temp]]){
    25             ge[cnt]++;
    26             visited[huan[x][temp]]=true;//这里容易蒙……
    27             temp=huan[x][temp];//temp指向了这个连的下一个,再次循环时判断的是下一个的下一个……
    28         }
    29     }
    30     memset(f,0,sizeof(f));  f[0][0][0]=1;
    31     for(int t=1;t<=cnt;t++)
    32         for(int i=sr;i>=0;i--)
    33             for(int j=sb;j>=0;j--)
    34                 for(int k=sg;k>=0;k--){
    35                     if(i>=ge[t])  f[i][j][k]=(f[i][j][k]+f[i-ge[t]][j][k])%p;
    36                     if(j>=ge[t])  f[i][j][k]=(f[i][j][k]+f[i][j-ge[t]][k])%p;
    37                     if(k>=ge[t])  f[i][j][k]=(f[i][j][k]+f[i][j][k-ge[t]])%p;
    38                 }
    39     return f[sr][sb][sg];
    40 }
    41 int main(){//freopen("ddd.in","r",stdin);
    42     cin>>sr>>sb>>sg>>m>>p;
    43     n=sr+sb+sg;
    44     for(int i=1;i<=m;i++)
    45         for(int j=1;j<=n;j++)
    46             scanf("%d",&huan[i][j]);
    47     m++;
    48     for(int i=1;i<=n;i++)  huan[m][i]=i;//注意还有不置换的情况
    49     for(int i=1;i<=m;i++)
    50         ans=(ans+dp(i))%p;
    51     int x,y;
    52     exgcd(m,p,x,y);
    53     while(x<=0)x+=p;
    54     cout<<ans*x%p<<endl;
    55     return 0;
    56 }
    View Code
  • 相关阅读:
    pip 8 安装
    zabbix server配置文件
    双代号网络图、双代号时标网络图
    logrotate
    tsql 执行存储过程
    dos 加用户
    Visual Studio (VS IDE) 你必须知道的功能和技巧
    格式化数字字符串 与C#变量
    .NET中的字符串你了解多少?
    新手如何有效地学习.NET
  • 原文地址:https://www.cnblogs.com/JSL2018/p/5911855.html
Copyright © 2011-2022 走看看