题意:用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 }
posted on 2012-09-10 10:42  DrunBee  阅读(2029)  评论(0编辑  收藏  举报