zoukankan      html  css  js  c++  java
  • 解题:HDU 5868 Different Circle Permutation

    题面

    先往上套Burnside引理

    既然要求没有$frac{2*π}{n}$的角,也就是说两个人不能挨着,那么相当于给一个环黑白染色,两个相邻的点不能染白色,同时求方案数。考虑$n$个置换子群,即向一边旋转i(1<=i<=n)个单位,那么每个置换子群下循环节的长度是$lcm(i,n)/i$,那循环节数目就是$n/(lcm(i,n)/i)=gcd(i,n)$,然后式子就出来了,设$p(i)$是给长度为$i$的环染色的方案

    $ans=frac{sumlimits_{i=1}^np(gcd(i,n))}{n}$

    如果我们能快速算$p$那么枚举$d=gcd(i,n)$即可,现在考虑如何算$p$,不妨先设$dp[i][0/1]$表示染了长度为$i$的环,两边白色的点的数目为$0/1$的方案数,转移显然

    $dp[i][0]=dp[i-1][0]+dp[i-1][1],dp[i][1]=dp[i-1][0]$

    可见$dp[i][0]$就是$i-1$的答案,$dp[i][1]$就是$dp[i-1][0]$也就是$i-2$的答案,所以$p[i]=p[i-1]+p[i-2]$,矩乘即可

    注意$n=1$“两边”都是可以染白色的,判掉

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int mod=1e9+7;
     6 struct a
     7 {
     8     int mat[2][2];
     9     void Clean()
    10     {
    11         memset(mat,0,sizeof mat);
    12     }
    13     void Init1()
    14     {
    15         Clean();
    16         mat[0][0]=1,mat[0][1]=3;
    17     }
    18     void Init2()
    19     {
    20         Clean();
    21         mat[0][1]=mat[1][0]=mat[1][1]=1;
    22     }
    23 };
    24 a Matime(a x,a y)
    25 {
    26     a ret; ret.Clean();
    27     for(int i=0;i<2;i++)
    28         for(int k=0;k<2;k++)
    29             for(int j=0;j<2;j++)
    30                 ret.mat[i][j]+=1ll*x.mat[i][k]*y.mat[k][j]%mod,ret.mat[i][j]%=mod;
    31     return ret;
    32 }
    33 a Maqpow(a x,int k)
    34 {
    35     if(k==1) return x;
    36     a tmp=Maqpow(x,k/2);
    37     return k%2?Matime(x,Matime(tmp,tmp)):Matime(tmp,tmp);
    38 }
    39 int Calc(int x)
    40 {
    41     if(x==1) return 1;
    42     if(x==2) return 3;
    43     a fir,cal; fir.Init1(),cal.Init2();
    44     cal=Maqpow(cal,x-2),fir=Matime(fir,cal);
    45     return fir.mat[0][1];
    46 }
    47 int Phi(int x)
    48 {
    49     int ret=x; 
    50     for(int i=2;i*i<=x;i++)
    51         if(x%i==0)
    52         {
    53             ret/=i,ret*=i-1;
    54             while(x%i==0) x/=i;
    55         }
    56     if(x!=1) ret/=x,ret*=x-1;
    57     return ret;
    58 }
    59 void exGCD(int a,int b,int &x,int &y)
    60 {
    61     if(!b) x=1,y=0;
    62     else exGCD(b,a%b,y,x),y-=a/b*x;
    63 }
    64 int Inv(int x)
    65 {
    66     int xx,yy;
    67     exGCD(x,mod,xx,yy);
    68     return (xx%mod+mod)%mod;
    69 }
    70 int Solve(int x)
    71 {
    72     if(x==1) return 2;
    73     int ret=0;
    74     for(int i=1;i*i<=x;i++)
    75         if(x%i==0) 
    76         {
    77             ret+=1ll*Phi(x/i)*Calc(i)%mod,ret%=mod;
    78             if(i*i!=x) ret+=1ll*Phi(i)*Calc(x/i)%mod,ret%=mod;
    79         }
    80     return 1ll*ret*Inv(x)%mod;
    81 }
    82 int main()
    83 {
    84     int n;
    85     while(scanf("%d",&n)!=EOF)
    86         printf("%d
    ",Solve(n));
    87     return 0;
    88 }
    View Code
  • 相关阅读:
    算法:最大回文子串问题
    Python HTTP库requests中文页面乱码解决方案!
    Python:默认参数
    在博客园开通个人博客了
    JQ选择器
    C# 接口
    C# 微信公众平台开发(2) 微信菜单
    C# 微信公众平台开发(1) 服务器配置
    博客园开博第一天!记录生活,扬帆启航!
    JavaScript判断、循环、Map、Set
  • 原文地址:https://www.cnblogs.com/ydnhaha/p/10306372.html
Copyright © 2011-2022 走看看