forked from yogykwan/acm-challenge-workbook
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpoj1286.cpp
53 lines (43 loc) · 1.22 KB
/
poj1286.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/*
* POJ 1286: Necklace of Beads
* 题意:三种颜色的珠子串称一定长度的链子,翻转或旋转后重合的视为同一种,求共有多少种不同的。
* 类型:Pólya计数
* 算法:L=|1/G|*(m^c(p1)+m^c(p2)+...+m^c(pk))。G为置换群,m为颜色,c(pi)表示第i个置换的循环节数。同时考虑翻转和旋转,置换群大小为2n。旋转i的循环节个数为gcd(n,i)。翻转时按奇偶讨论,n为奇数时为1+(n-1)/2,共n条对称轴;偶数时对称轴分过不过珠子两种,各n/2种情况,循环节分别为(n-2)/2+2+1和n/2。
*/
#include <cstdio>
typedef long long LL;
LL Gcd(LL a, LL b) {
for (LL t; t = b;) {
b = a % b;
a = t;
}
return a;
}
LL Pow(LL a, LL b) {
LL ans = 1;
while (b--) ans *= a;
return ans;
}
int main() {
LL n;
while (scanf("%lld", &n) != EOF && n != -1) {
if (n == 0) {
printf("0\n");
continue;
}
LL ans = 0;
// rotation
for (LL i = 0; i < n; ++i) {
ans += Pow(3, Gcd(n, i));
}
// reflection
if (n & 1) {
ans += n * Pow(3, n / 2 + 1);
} else {
ans += n / 2 * (Pow(3, n / 2 + 1) + Pow(3, n / 2));
}
ans /= 2 * n;
printf("%lld\n", ans);
}
return 0;
}