有 n 顆珠子串成項鍊,每顆可染 c 種顏色。項鍊可旋轉、翻轉(二面體群 Dn)。求本質不同的染色方案數。
答案 = (1 / |G|) × Σg∈G ck(g)
| 操作類型 | 數量 | 循環數 k(g) |
|---|---|---|
| 旋轉 0 步(恆等) | 1 | n |
| 旋轉 i 步 (1≤i<n) | n-1 | gcd(n, i) |
| 翻轉(n 奇) | n | n/2 + 1 (整數除法) |
| 翻轉(n 偶) | n/2 | n/2 + 1 (對頂點翻轉) |
| n/2 | n/2 (對邊翻轉) |
ans = ( Σ_{i=0}^{n-1} c^{gcd(n,i)} // 旋轉
+ (n%2 ? n * c^{n/2+1} // 奇數翻轉
: n/2 * c^{n/2+1} + n/2 * c^{n/2} ) // 偶數翻轉
) / (2*n)
long long qpow(long long a, long long b) {
long long r = 1;
while (b) {
if (b & 1) r *= a;
a *= a; b >>= 1;
}
return r;
}
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
ll gcd(ll a, ll b) { return b ? gcd(b, a%b) : a; }
ll qpow(ll a, ll b) { ll r=1; while(b){ if(b&1) r*=a; a*=a; b>>=1; } return r; }
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
ll c, n;
while (cin >> c >> n) {
if (c == 0 && n == 0) break;
ll sum = 0;
// 旋轉
for (ll i = 0; i < n; ++i) sum += qpow(c, gcd(n, i));
// 翻轉
if (n & 1) sum += n * qpow(c, n/2 + 1);
else sum += (n/2) * qpow(c, n/2 + 1) + (n/2) * qpow(c, n/2);
cout << sum / (2*n) << '\n';
}
return 0;
}
n/2 在 C++ 中自動向下取整,符合公式。i=0 時對應恆等旋轉,循環數 n,公式自動涵蓋。