zoukankan      html  css  js  c++  java
  • bzoj1004题解

    【题意分析】

      给N个元素染色,可以在定置换群的作用下互相转化的染色方案算相同的,问本质不同的染色方案数。

    【解题思路】

      引理:Burnside定理

    设集合S=[1,n]∩N,记等价类数为L,给定S上的置换群G。

    Zk (k不动置换类):若k是S中某个元素,G中使k保持不变的置换的全体,记以Zk,叫做G中使k保持不动的置换类,简称k不动置换类。

    C(π)(置换n的不动点全集):对于一个置换π∈G,及a∈X,若π(a)=a,则称a为π的不动点。π的不动点的全体记为C(π)。

    有定理:L=1/|G|*∑|Zk|(k∈S)=1/|G|*Σ|C(n)|(n∈G)。

      所以,我们只要分别计算G中每个置换的不动点数,就可以计算出等价类数。外层复杂度O(m)。

      考虑染色,对于每个置换,在同一个置换环中的元素必定染成同色,才能保证集合range(n)经过置换后染色方案不变,所以可以用三维背包来计算方案数。内层复杂度O(SrSgSb+n)。

      总复杂度O(n^2+nSrSgSb)。

    【参考代码】

      1 #include <cmath>
      2 #include <cstdio>
      3 #define REP(I,start,end) for(int I=(start);I<=(end);I++)
      4 #define PER(I,start,end) for(int I=(start);I>=(end);I--)
      5 #define REPs(I,start,end,step) for(int I=(start);I<=(end);I+=(step))
      6 #define PERs(I,start,end,step) for(int I=(start);I>=(end);I-=(step))
      7 using namespace std;
      8 typedef unsigned short US;
      9 typedef unsigned long UL;
     10 typedef long long LL;
     11 typedef unsigned long long ULL;
     12 inline int getint()
     13 {
     14     char ch=getchar();
     15     while((ch<'0'||ch>'9')&&ch!='-')
     16         ch=getchar();
     17     int result=0;
     18     bool impositive=ch=='-';
     19     if(impositive)
     20         ch=getchar();
     21     while(ch>='0'&&ch<='9')
     22     {
     23          result=(result<<3)+(result<<1)+ch-'0';
     24         ch=getchar();
     25     }
     26     return impositive?-result:result;
     27 }
     28 inline int putint(int n)
     29 {
     30     int result=1;
     31     char* sav=new char[20];
     32     bool impositive=n<0;
     33     if(impositive)
     34     {
     35         putchar('-');
     36         n=-n;
     37     }
     38     sav[0]=n%10+'0';
     39     while(n/=10)
     40         sav[result++]=n%10+'0';
     41     PER(i,result-1,0)
     42         putchar(sav[i]);
     43     delete []sav;
     44     return result+impositive;
     45 }
     46 inline LL getLL()
     47 {
     48     char ch=getchar();
     49     while((ch<'0'||ch>'9')&&ch!='-')
     50         ch=getchar();
     51     LL result=0ll;
     52     bool impositive=ch=='-';
     53     if(impositive)
     54         ch=getchar();
     55     while(ch>='0'&&ch<='9')
     56     {
     57          result=(result<<3)+(result<<1)+ch-'0';
     58         ch=getchar();
     59     }
     60     return impositive?-result:result;
     61 }
     62 inline int putLL(LL n)
     63 {
     64     int result=1;
     65     char* sav=new char[20];
     66     bool impositive=n<0;
     67     if(impositive)
     68     {
     69         putchar('-');
     70         n=-n;
     71     }
     72     sav[0]=n%10+'0';
     73     while(n/=10)
     74         sav[result++]=n%10+'0';
     75     PER(i,result-1,0)
     76         putchar(sav[i]);
     77     delete []sav;
     78     return result+impositive;
     79 }
     80 template<typename integer> inline int read_int(integer &n)
     81 {
     82     char ch=getchar();
     83     while((ch<'0'||ch>'9')&&ch!='-')
     84         ch=getchar();
     85     int result=n=integer(0);
     86     bool impositive=ch=='-';
     87     if(impositive)
     88         ch=getchar();
     89     while(ch>='0'&&ch<='9')
     90     {
     91          n=(n<<3)+(n<<1)+integer(ch-'0');
     92          result++;
     93         ch=getchar();
     94     }
     95     if(impositive)
     96     {
     97         n=-n;
     98         result++;
     99     }
    100     return result;
    101 }
    102 template<typename integer> inline int write_int(integer n)
    103 {
    104     int result=1;
    105     char* sav=new char[20];
    106     bool impositive=n<0;
    107     if(impositive)
    108     {
    109         putchar('-');
    110         n=-n;
    111     }
    112     sav[0]=n%10+'0';
    113     while(n/=10)
    114         sav[result++]=n%10+'0';
    115     PER(i,result-1,0)
    116         putchar(sav[i]);
    117     delete []sav;
    118     return result+impositive;
    119 }
    120 template<typename integer> inline integer sqr(integer n)
    121 {
    122     return n*n;
    123 }
    124 template<typename base_type,typename exp_type> inline base_type PowerMod(base_type Base,exp_type Exp,base_type Mod)
    125 {
    126     bool* sav=new bool[int(log(Exp)/log(2))+1];
    127     int tot=0;
    128     base_type result=base_type(1),baser=Base%Mod;
    129     exp_type tmp=Exp;
    130     while(tmp)
    131     {
    132         sav[tot++]=tmp&1;
    133         tmp>>=1;
    134     }
    135     while(tot)
    136     {
    137         result=sqr(result)%Mod;
    138         if(sav[--tot])
    139             result=result*baser%Mod;
    140     }
    141     delete []sav;
    142     return result;
    143 }
    144 //====================================Header Template===================================
    145 #include <cstring>
    146 bool used[100];
    147 int sr,sb,sg,n,p,trans[100],cnt[100],f[30][30][30];
    148 inline int mod_reverse(int _n,int _p)
    149 {
    150     return PowerMod(_n,_p-2,_p);
    151 }
    152 inline int DP()
    153 {
    154     memset(f,0,sizeof(f));
    155     memset(used,0,sizeof(used));
    156     int group=0;
    157     REP(i,1,n)
    158         if(!used[i])
    159         {
    160             used[i]=true;
    161             int j=trans[i],tot=1;
    162             while(!used[j])
    163             {
    164                 used[j]=true;
    165                 tot++;
    166                 j=trans[j];
    167             }
    168             cnt[++group]=tot;
    169         }
    170     f[0][0][0]=1;
    171     REP(g,1,group)
    172         PER(i,sr,0)
    173             PER(j,sb,0)
    174                 PER(k,sg,0)
    175                 {
    176                     if(i>=cnt[g])
    177                         (f[i][j][k]+=f[i-cnt[g]][j][k])%=p;
    178                     if(j>=cnt[g])
    179                         (f[i][j][k]+=f[i][j-cnt[g]][k])%=p;
    180                     if(k>=cnt[g])
    181                         (f[i][j][k]+=f[i][j][k-cnt[g]])%=p;
    182                 }
    183     return f[sr][sb][sg];
    184 }
    185 int main()
    186 {
    187     sr=getint();
    188     sb=getint();
    189     sg=getint();
    190     int m=getint();
    191     p=getint();
    192     n=sr+sb+sg;
    193     int ans=0;
    194     REP(i,1,m)
    195     {
    196         REP(j,1,n)
    197             trans[j]=getint();
    198         (ans+=DP())%=p;
    199     }
    200     REP(i,1,n)
    201         trans[i]=i;
    202     (ans+=DP())%=p;
    203     putint(ans*mod_reverse(m+1,p)%p);
    204     return 0;
    205 }
    View Code
    We Secure, We Contain, We Protect.
  • 相关阅读:
    jedis jedispool Redistemplate
    开箱一个docker
    JPA分页查询与条件分页查询
    基于token与基于服务器的身份认证
    uni-app第三方登陆-微信
    main.js中封装全局登录函数
    idea搭建可运行Servlet的Web项目[maven]
    什么是servlet?
    简单了解request与response
    颓废的三天
  • 原文地址:https://www.cnblogs.com/spactim/p/6424442.html
Copyright © 2011-2022 走看看