polya 计数,首先算出有多少种旋转方式,n个点串成环,
如果旋转的话有n种;
其次,如果n为偶数,可以沿着两个顶点翻转,或者沿着
两个顶点之间翻转, 总的加一起是2*n种,同理,奇数
算出来也是2*n中,对于每种翻转,需要求循环节的个数
普通旋转的时候 如果旋转k(0<=k<=n-1)那么 循环节个数
是gcd(k,n),这是因为:在每次旋转k个单位的时候看看要
经过旋转多少次能归回原位,比如是x次。
那么x*k%n=0 所以 x*k=y*n 令x=n,y=k,所以x的最小值为
n/gcd(n,k),那么循环节个数为 n/(n/gcd(n,k))=gcd(n,k)
至于旋转画画就可以了
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
ll quick_pow(ll a,ll n) //log(n) 计算a^n
{
ll ans=1,base=a;
while(n!=0){
if(n&1!=0)
ans*=base;
base*=base;
n>>=1;
}
return ans;
}
ll gcd(ll a,ll b)
{
return a==0?b:gcd(b%a,a);
}
int main()
{
ll n;
ll first,second;
while(scanf("%lld",&n)!=EOF)
{
if(n==0)
{
printf("0\n");
continue;
}
first=second=0;
if(n==-1) break;
if(n%2==0)
{
second=2*n;
first+=quick_pow(3,n);
for(int i=1;i<n;i++)
first+=quick_pow(3,gcd(i,n));
first+=n/2*quick_pow(3,n/2);
first+=n/2*quick_pow(3,n/2+1);
}
else
{
second=2*n;
first+=quick_pow(3,n);
for(int i=1;i<n;i++)
first+=quick_pow(3,gcd(i,n));
first+=n*quick_pow(3,(n+1)/2);
}
printf("%lld\n",first/second);
}
return 0;
}
/*
polya 计数,首先算出有多少种旋转方式,n个点串成环,
如果旋转的话有n种;
其次,如果n为偶数,可以沿着两个顶点翻转,或者沿着
两个顶点之间翻转, 总的加一起是2*n种,同理,奇数
算出来也是2*n中,对于每种翻转,需要求循环节的个数
普通旋转的时候 如果旋转k(0<=k<=n-1)那么 循环节个数
是gcd(k,n),这是因为:在每次旋转k个单位的时候看看要
经过旋转多少次能归回原位,比如是x次。
那么x*k%n=0 所以 x*k=y*n 令x=n,y=k,所以x的最小值为
n/gcd(n,k),那么循环节个数为 n/(n/gcd(n,k))=gcd(n,k)
至于旋转简单画画就可以了
*/