题意:用k种不同的颜色给长度为n的项链染色。
题解:
1.旋转置换:一个有n个旋转置换,依次为旋转0,1,2,```n-1。对每一个旋转置换,它循环分解之后得到的循环因子个数为gcd(n,i).
2.翻转置换:分奇偶讨论。
奇数的时候 翻转轴 = (顶点+对边终点的连线),一共有n个顶点,故有n个置换,且每个置换分解之后的因子个数为n/2+1;
偶数的时候 翻转轴 = (顶点+顶点的连线),一共有n个顶点,故有n/2个置换,且每个置换分解之后的因子个数为n/2+1; 或者 翻转轴 = (边终点+边中点的连线),一共有n个顶点,故有n/2个置换,且每个置换分解之后的因子个数为n/2;
#include<cmath>
#include<cstdio>
using namespace std;
#define lint __int64
int gcd ( int a, int b )
{
return b ? gcd ( b, a % b ) : a;
}
lint exp ( lint a, int b )
{
lint ret = 1;
while ( b >= 1 )
{
if ( b & 1 ) ret *= a;
a = a * a;
b >>= 1;
}
return ret;
}
lint Polya ( int k, int n )
{
lint ret = 0;
for ( int i = 0; i < n; i++ )
ret += exp (k, gcd (n,i));
if ( n & 1 )
ret += n * exp (k,n/2+1);
else
ret += n/2 * exp(k,n/2) + n/2 * exp(k,n/2+1);
return ret / n / 2;
}
int main()
{
int k, n;
while ( scanf("%d%d",&k,&n) && (k||n) )
printf("%I64d\n",Polya(k,n));
return 0;
}
POJ 1286 Necklace of Beads
#include<cstdio>
#define lint __int64
lint power ( lint a, lint b )
{
lint ret = 1;
while ( b >= 1 )
{
if ( b & 1 ) ret *= a;
a = a * a;
b >>= 1;
}
return ret;
}
lint gcd ( lint a, lint b )
{
return b ? gcd(b, a % b) : a;
}
lint polya ( lint n )
{
lint ret = 0;
for ( int i = 0; i < n; i++ )
ret += power(3, gcd(i,n));
if ( n & 1 )
ret += n * power(3,n/2+1);
else
ret += n/2 * power(3,n/2) + n/2 * power(3,n/2+1);
return ret / n / 2;
}
int main()
{
lint n;
while ( scanf("%I64d",&n) && n != -1 )
{
if ( n <= 0 ) printf("0\n");
else printf("%I64d\n",polya(n));
}
return 0;
}