Sgu294He's Circles

Description
有一个长度为N的环,上面写着’X’和’E’,问本质不同的环有多少种。(N不超过200000)。

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
3

Sample Output
4


polya裸题,和[POJ2154]Color一样,只是需要带个高精度罢了,只有两种颜色,不用取模

/*program from Wolfycz*/
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x7f7f7f7f
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline int read(){
    int x=0,f=1;char ch=getchar();
    for (;ch<'0'||ch>'9';ch=getchar())  if (ch=='-')    f=-1;
    for (;ch>='0'&&ch<='9';ch=getchar())    x=(x<<1)+(x<<3)+ch-'0';
    return x*f;
}
inline void print(int x){
    if (x>=10)     print(x/10);
    putchar(x%10+'0');
}
const int N=2e5;
const int base=1e4;
const int digit=4;
const int maxn=1e2;
struct Bignum{
    int len,v[maxn];
    Bignum(){len=1,memset(v,0,sizeof(v));}
    void init(){v[0]=1;}
    void write(){
        printf("%d",v[len-1]);
        for (int i=len-2;~i;i--)    printf("%0*d",digit,v[i]);
        putchar('\n');
    }
};
int prime[N+10],phi[N+10];
bool inprime[N+10];
int tot;
void prepare(){
    phi[1]=1;
    for (int i=2;i<=N;i++){
        if (!inprime[i])    prime[++tot]=i,phi[i]=i-1;
        for (int j=1;j<=tot&&prime[j]*i<=N;j++){
            inprime[prime[j]*i]=1;
            if (i%prime[j]==0)  phi[i*prime[j]]=phi[i]*prime[j];
            else    phi[i*prime[j]]=phi[i]*(prime[j]-1);
        }
    }
}
Bignum operator +(const Bignum &x,const Bignum &y){
    Bignum z;
    z.len=max(x.len,y.len);
    for (int i=0;i<=z.len;i++)  z.v[i]+=x.v[i]+y.v[i],z.v[i+1]+=z.v[i]/base,z.v[i]%=base;
    while (z.v[z.len])  z.v[z.len+1]+=z.v[z.len]/base,z.v[z.len]%=base,z.len++;
    return z;
}
Bignum operator *(const Bignum &x,const Bignum &y){
    Bignum z;
    z.len=x.len+y.len;
    for (int i=0;i<=x.len;i++)
        for (int j=0;j<=y.len;j++)
            z.v[i+j]+=x.v[i]*y.v[j],z.v[i+j+1]+=z.v[i+j]/base,z.v[i+j]%=base;
    while (z.len!=1&&!z.v[z.len])   z.len--;z.len++;
    while (z.v[z.len])  z.v[z.len+1]+=z.v[z.len]/base,z.v[z.len]%=base,z.len++;
    return z;
}
Bignum operator /(Bignum &x,int y){
    for (int i=x.len;~i;i--)    x.v[i-1]+=x.v[i]%y*base,x.v[i]/=y;
    while (x.len!=1&&!x.v[x.len])   x.len--;
    while (x.v[x.len])  x.v[x.len+1]+=x.v[x.len]/base,x.v[x.len]%=base,x.len++;
    return x;
}
Bignum mlt(Bignum a,int b){
    Bignum res;res.init();
    for (;b;b>>=1,a=a*a)    if (b&1)    res=res*a;
    return res;
}
Bignum change(int x){
    Bignum z;
    while (x){
        z.v[z.len-1]=x%base;
        z.len++;
        x/=base;
    }
    while (z.len!=1&&!z.v[z.len])   z.len--;
    while (z.v[z.len])  z.v[z.len+1]+=z.v[z.len]/base,z.v[z.len]%=base,z.len++;
    return z;
}
int main(){
    prepare();
    int n=read();
    Bignum Two,Ans;
    Two.v[0]=2;
    for (int i=1;i*i<=n;i++){
        if (n%i)    continue;
        int j=n/i;
        Ans=Ans+mlt(Two,i)*change(phi[j]);
        if (i!=j)   Ans=Ans+mlt(Two,j)*change(phi[i]);
    }
    Ans=Ans/n;
    Ans.write();
    return 0;
}

转载于:https://www.cnblogs.com/Wolfycz/p/8525073.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值