zoukankan      html  css  js  c++  java
  • 数学计数原理(Pólya,高精度):SGU 294 He's Circles

     

    He's Circles

    He wrote n letters "X" and "E" in a circle. He thought that there were 2n possibilities to do it, because each letter may be either "X" or "E". But Qc noticed that some different sequences of letters can be transformed one to another with a circular shift (thus representing actually the same circular string).
    For example, strings "XXE"-"XEX"-"EXX" are actually the same.
    Qc wants to know how many different circular strings of n letters exist. Help him to find that out.

    Input

    The input file contains a single integer 1 <= n <= 200000.

    Output

    Output a single integer --- the number circular strings of length n.

    Sample Input


    Sample test(s)

    Input
    Test #1
    3

    Test #2
    4

    Output
    Test #1
    4

    Test #2
    6
      这道题是等价类计数问题。
      由于是我写的第一题,我会把过程写的尽量详细,用以纪念。
      题意:有一个长度为N的环,上面写着’X’和’E’,问本质不同的环有多少种。(N不超过200000)。
      考虑用Pólya定理,答案是Σ(每个置换的不动点个数)/n,如何求不动点个数?这里枚举所有置换,假设当前枚举到的置换为"循环移动k位",d=(n,k),若1位置在当前置换下可以到3位置,则1位置和3位置处在同一循环,这时循环的个数就是d(每个循环经过n*k/d个点,由于每个间距为k,所以一个循环有n/d个点,那么就有d个循环),这对答案的贡献就是2^d(每个循环中可涂任意相同颜色,不影响其为不动点),所以就可以枚举d,这时我们可以知道与n的GCD为d的数有φ(n/d)个,那么这里答案则为1/n*Σ2^d*φ(n/d)。
      然后还要用高精度,真羡慕JAVA。
      1 #include <iostream>
      2 #include <cstring>
      3 #include <cstdio>
      4 using namespace std;
      5 const int maxn=200010;
      6 int n,tot;
      7 int phi[maxn],pri[maxn];
      8 
      9 void Linear_Shaker(){
     10     phi[1]=1;
     11     for(int i=2;i<=n;i++){
     12         if(!phi[i]){
     13             phi[i]=i-1;
     14             pri[++tot]=i;
     15         }
     16         for(int j=1;j<=n;j++){
     17             if(i*pri[j]>n)break;
     18             if(i%pri[j]!=0)
     19                 phi[i*pri[j]]=phi[i]*(pri[j]-1);
     20             else{
     21                 phi[i*pri[j]]=phi[i]*pri[j];
     22                 break;
     23             }    
     24         }
     25     }
     26 }
     27 
     28 int POW[4]={1,10,100,1000};
     29 const int mod=10000;
     30 struct ExtInt{
     31     int num[20010],len;
     32     ExtInt(int x){len=0;
     33         memset(num,0,sizeof(num));
     34         do{
     35             num[++len]=x%mod;
     36             x/=mod;
     37         }while(x);
     38     }
     39     
     40     void Scf(){
     41         char s[10010];scanf("%s",s+1);
     42         memset(num,0,sizeof(num));len=1;
     43         for(int i=strlen(s+1),cnt=0;i>=1;i--){
     44             num[len]+=POW[cnt++]*(s[i]-'0');
     45             if(cnt==4)cnt=0,len+=1;
     46         }
     47     }
     48     
     49     int operator [](int x){
     50         return num[x];
     51     }    
     52     
     53     void Prf(){
     54         printf("%d",num[len]);
     55         for(int i=len-1;i>=1;i--)
     56             printf("%04d",num[i]);
     57         printf("
    ");    
     58     }
     59 };
     60 
     61 ExtInt operator +(ExtInt a,int b){
     62     ExtInt ret(0);
     63     ret.len=a.len;
     64     for(int i=1,in=0;i<=ret.len||in;i++){
     65         ret.num[i]=a[i]+b+in;in=ret[i]/mod;
     66         ret.num[i]%=mod;ret.len=max(ret.len,i);
     67     }
     68     return ret;
     69 }
     70 
     71 ExtInt operator +(ExtInt a,ExtInt b){
     72     ExtInt ret(0);
     73     ret.len=max(a.len,b.len);
     74     for(int i=1,in=0;i<=ret.len||in;i++){
     75         ret.num[i]=a[i]+b[i]+in;in=ret[i]/mod;
     76         ret.num[i]%=mod;ret.len=max(ret.len,i);
     77     }
     78     return ret;
     79 }
     80 
     81 ExtInt operator *(ExtInt a,ExtInt b){
     82     ExtInt ret(0);
     83     for(int i=1;i<=a.len;i++){
     84         for(int j=1,in=0;j<=b.len||in;j++){    
     85             ret.num[i+j-1]+=a[i]*b[j]+in;in=ret[i+j-1]/mod;
     86             ret.num[i+j-1]%=mod;ret.len=max(ret.len,i+j-1);
     87         }
     88         while(!ret[ret.len])
     89             ret.num[ret.len--]=0;
     90         ret.len=max(ret.len,1);    
     91     }
     92     return ret;
     93 }
     94 
     95 ExtInt operator ^(ExtInt a,int k){
     96     ExtInt ret(1);
     97     while(k){
     98         if(k&1)ret=ret*a;
     99         k>>=1;a=a*a;    
    100     }
    101     return ret;
    102 }
    103 
    104 ExtInt operator /(ExtInt a,int k){
    105     for(int i=a.len,tot=0;i>=1;i--){
    106         tot=tot*10000+a[i];
    107         a.num[i]=tot/k;
    108         tot%=k;
    109     }
    110     while(!a[a.len])
    111         a.num[a.len--]=0;
    112     return a;
    113 }
    114 
    115 int GCD(int a,int b){
    116     return b?GCD(b,a%b):a;
    117 }
    118 
    119 int main(){
    120     scanf("%d",&n);
    121     Linear_Shaker();
    122     ExtInt ans(0);
    123     for(int d=1;d<=n;d++)
    124         if(n%d==0){
    125             ExtInt x(2);
    126             ans=ans+(x^d)*phi[n/d];
    127         }
    128     ans=ans/n;    
    129     ans.Prf();
    130     return 0;
    131 }
  • 相关阅读:
    102/107. Binary Tree Level Order Traversal/II
    110. Balanced Binary Tree
    SQL SERVER select,update,delete使用表别名
    C# 有哪些集合
    C# 流总结
    How ASP.NET MVC Works ? (Artech)
    c#扩展方法
    使用缓存的九大误区
    9中浏览器端缓存
    理解AppDomain和AppPool
  • 原文地址:https://www.cnblogs.com/TenderRun/p/5656038.html
Copyright © 2011-2022 走看看