http://poj.org/problem?id=2409 (题目链接)
一个n个珠子的项链,每个珠子可以被染成t种颜色。项链可以翻转和旋转,问不同的染色方案数。
Pólya定理。
旋转:如果逆时针旋转i颗珠子的间距,则珠子0,i,2i,······构成一个循环。这个循环有n/gcd(n,i)个元素。根据对称性,所有循环的长度相同,因此一共有gcd(n,i)个循环。这些置换的不动点总数为${\sum_{i=0}^{n-1} t^{gcd(i,n)}}$种,其中t为颜色数。
翻转:需要分两种情况讨论。当n为奇数时,对称轴有n条,每条对称轴形成${\frac{n-1}{2}}$个长度为2的循环和1个长度为1的循环,即一共${\frac{n+1}{2}}$个循环。这些置换的不动点总数为${b = n t^{ \frac{n+1}{2} }}$。当n为偶数时,有两种对称轴。穿过柱子的对称轴有${\frac{n}{2}}$条,各形成${\frac{n}{2}-1}$个长度为2的循环和两个长度为1的循环;不穿过珠子的对称轴有${\frac{n}{2}}$条,各形成${\frac{n}{2}}$个长度为2的循环。这些置换的不动点总数为${b=\frac{n}{2} (t^{\frac{n}{2}+1}+t^{\frac{n}{2}})}$。
// poj2409 #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> #define LL long long #define inf 1<<30 #define Pi acos(-1.0) #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout); using namespace std; LL gcd(LL a,LL b) { return b==0 ? a : gcd(b,a%b); } LL power(LL a,LL b) { LL res=1; while (b) { if (b&1) res*=a; b>>=1;a*=a; } return res; } int main() { LL n,t; while (scanf("%lld%lld",&t,&n)!=EOF && n && t) { LL a=0,b=0; for (int i=0;i<n;i++) a+=power(t,gcd(n,i)); if (n&1) b=n*power(t,(n+1)/2); else b=n/2*(power(t,n/2+1)+power(t,n/2)); printf("%lld\n",(a+b)/2/n); } return 0; }
原文:http://www.cnblogs.com/MashiroSky/p/6257534.html