zoukankan      html  css  js  c++  java
  • bzoj1478 Sgu282 Isomorphism

    这道题也是一道不错的找规律polya原理的题

    我们可以发现,对于两种点的置换,如果他们的循环节完全一样,那么他们对于边的置换的循环也完全一样。

    我们又会发现,当一条边两侧的点位于同一循环中时,这些边构成的循环节共有${frac{L_{i}}{2}}$个,$L_{i}$表示点的循环节长度

    当两点位于两个循环中时,这些变构成的循环节共有$gcd(L_{i},L_{j})$个。

    然后我们需要算出每种点的置换的方案数,这个写着不方便,看代码吧

    于是我们可以dfs出每种点的置换,然后求出对应边的置换的循环节数以及方案数,最后上polya就好了!

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <cmath>
     6 #define int long long
     7 using namespace std;
     8 int n,m,mod;
     9 int qp(int a,int b){
    10     int c=1;
    11     while(b){
    12         if(b&1)c=c*a%mod;
    13         a=a*a%mod; b>>=1;
    14     }return c;
    15 }
    16 int l[66],C[66][66],fac[66],ny[66],g[66][66];
    17 int gcd(int a,int b){return !b?a:gcd(b,a%b);}
    18 int all,cnt,sum,ans;
    19 void dfs(int x,int last,int num){
    20     if(x==n+1){
    21         sum=0;
    22         for(int i=1;i<=num;i++)sum+=l[i]/2;
    23         for(int i=1;i<=num;i++)
    24             for(int j=i+1;j<=num;j++)sum+=g[l[i]][l[j]];
    25         cnt=1;
    26         for(int i=1,rest=n,j;i<=num;i++){
    27             j=i;
    28             while(j<=num&&l[j]==l[i]){
    29                 (cnt*=C[rest][l[j]]*fac[l[j]-1]%mod)%=mod;
    30                 rest-=l[j];j++;
    31             }
    32             (cnt*=ny[j-i])%=mod;
    33             i=j-1;
    34              
    35         }
    36         (all+=cnt)%=mod;
    37         (ans+=cnt*qp(m,sum)%mod)%=mod;
    38         return ;
    39     }
    40     for(int i=last;x+i<=n+1;i++){
    41         l[num+1]=i;
    42         dfs(x+i,i,num+1);
    43     }
    44 }
    45 signed main(){
    46     scanf("%lld%lld%lld",&n,&m,&mod);
    47     fac[0]=1;
    48     for(int i=1;i<=n;i++){
    49         fac[i]=i*fac[i-1]%mod;
    50         ny[i]=qp(fac[i],mod-2);
    51     }
    52     for(int i=1;i<=n;i++)
    53         for(int j=1;j<=n;j++)g[i][j]=g[j][i]=gcd(i,j);
    54     for(int i=0;i<=n;i++){
    55         C[i][0]=1;
    56         for(int j=1;j<=i;j++)
    57             C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
    58     }
    59     dfs(1,1,0);
    60     ans=(ans*qp(all,mod-2))%mod;
    61     printf("%lld
    ",ans);
    62     return 0;
    63 }
    View Code
  • 相关阅读:
    POJ 2636:Electrical Outlets
    POJ 2260:Error Correction
    POJ 2080:Calendar
    POJ 2017:Speed Limit
    POJ 1504:Adding Reversed Numbers
    POJ 1477:Box of Bricks
    POJ 1060:Modular multiplication of polynomials
    HDU 1379:DNA Sorting
    HDU 1009:FatMouse' Trade
    mysql修改初始密码
  • 原文地址:https://www.cnblogs.com/Ren-Ivan/p/8470530.html
Copyright © 2011-2022 走看看