题意:用k种颜色对n个珠子构成的环上色,旋转翻转后相同的只算一种,求不等价的着色方案数。
Burnside定理的应用:
当n为奇数时,有n种翻转,每种翻转都是以一个顶点和该顶点对边的中点对称。有k^(n/2+1)*n种。
当n为偶数时,有n种翻转,其中一半是以两个对应顶点,另一半是以两条对边对称。有k^(n/2+1)*n/2+k^(n/2)*n/2种。
考虑旋转:枚举旋转角度360/n*i,(0<i<=n),也就是一个置换。经过该置换,颜色仍保持不变的着色方案有k^GCD(n,i)种。
一个长度为n的环,每i个上同一种颜色,可以上多少种颜色。
假设起点在x,则x,x+i,x+2*i,……,x+k*i,……
假设在第t次,第一次回到起点,则x=(x+t*i)%n => t*i%n=0 => t=LCM(i,n)/i=n*i/GCD(n,i)/i=n/GCD(n,i)。
那么可以上n/t种颜色,即n/(n/GCD(n,i))种,所以旋转的着色方案有k^GCD(n,i)种。
1 #include<cstdio> 2 typedef long long LL; 3 LL Pow(LL a, LL b) { 4 LL ans; 5 for (ans = 1; b; b >>= 1) { 6 if (b & 1) 7 ans *= a; 8 a *= a; 9 } 10 return ans; 11 } 12 int GCD(int x, int y) { 13 return y ? GCD(y, x % y) : x; 14 } 15 int main() { 16 int n, k, i; 17 LL ans; 18 while (scanf("%d%d", &k, &n), n || k) { 19 if (n & 1) 20 ans = Pow(k, n / 2 + 1) * n; 21 else 22 ans = Pow(k, n / 2 + 1) * (n / 2) 23 + Pow(k, n / 2) * (n / 2); 24 for (i = 1; i <= n; i++) 25 ans += Pow(k, GCD(n, i)); 26 ans = printf("%lld\n", ans / (2 * n)); 27 } 28 return 0; 29 }