用 c 種顏色給 n 個珠子的項鍊染色。項鍊可旋轉、翻轉。求本質不同的染色方案數。
方案數 = (1/|G|) · Σ_{g∈G} c^{cycles(g)}
| 操作類型 | 數量 | 循環數 | 貢獻 |
|---|---|---|---|
| 旋轉 0 步 (恆等) | 1 | n | cⁿ |
旋轉 i 步 (1≤i| n-1 | gcd(n,i) | c^{gcd(n,i)} | |
| 翻轉 (n 奇數) | n | n/2 + 1 | n·c^{n/2+1} |
| 翻轉 (n 偶數) | n/2 | n/2 + 1 | (n/2)·c^{n/2+1} |
| n/2 | n/2 | (n/2)·c^{n/2} |
#include
#include
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) { return b ? gcd(b, a%b) : a; }
ll qpow(ll a, ll n) {
ll r = 1;
while (n) {
if (n & 1) r *= a;
a *= a;
n >>= 1;
}
return r;
}
int main() {
ll c, n;
while (~scanf("%lld%lld", &c, &n)) {
if (c == 0 && n == 0) break;
ll ans = qpow(c, n); // 恆等旋轉
for (int i = 1; i < n; i++) // 非恆等旋轉
ans += qpow(c, gcd(n, i));
if (n & 1) // n 奇數
ans += n * qpow(c, n/2 + 1);
else { // n 偶數
ans += (n/2) * qpow(c, n/2 + 1);
ans += (n/2) * qpow(c, n/2);
}
printf("%lld\n", ans / (2*n));
}
return 0;
}
Input:
3 4
0 0
c=3, n=4
旋轉: 3⁴ + 3^{gcd(4,1)} + 3^{gcd(4,2)} + 3^{gcd(4,3)} = 81 + 3 + 9 + 3 = 96
翻轉: 2×3^{4/2+1} + 2×3^{4/2} = 2×27 + 2×9 = 72
總和 = 168, 除以 2n=8 → 21
Output: 21
Polya 計數是組合數學神器,核心步驟:
推薦資料:《組合數學》(盧開澤)、Polya 原著《Combinatorial Enumeration》、在線課程 MIT 6.042J。