Burnside và Polya (Đếm với đối xứng)
Bổ đề Burnside và Định lý Polya đếm số cấu hình phân biệt về mặt đối xứng — hai cấu hình được coi là giống nhau nếu có thể chuyển từ cái này sang cái kia bằng một phép biến đổi trong nhóm đối xứng.
Bổ đề Burnside
Số quỹ đạo phân biệt (số cấu hình khác nhau) dưới tác dụng của nhóm :
trong đó là số phần tử của tập bất động (fixed) dưới phép biến đổi .
Ví dụ 1: Tô màu vòng tròn
Đếm số vòng chuỗi hạt, mỗi hạt màu, phân biệt khi không thể xoay thành nhau.
Nhóm = nhóm quay (xoay ).
Phép quay (xoay vị trí): số hạt bất động = số chuỗi bất biến khi xoay bước.
Chuỗi bất biến khi xoay bước ⟺ chu kỳ chia ⟺ số màu.
long long count_necklace(int n, int k, long long MOD) {
long long ans = 0;
for (int j = 0; j < n; j++) {
int g = __gcd(n, j == 0 ? n : j);
ans = (ans + power(k, g, MOD)) % MOD;
}
return ans * power(n, MOD - 2, MOD) % MOD;
}
Ví dụ 2: Tô màu mặt xúc xắc
Đếm số cách tô 6 mặt xúc xắc với màu, phân biệt khi không thể xoay thành nhau.
Nhóm quay khối lập phương có phép quay. Tính cho từng loại phép quay:
// Nhóm quay khối lập phương: 24 phép quay
// Phân loại:
// - 1 phép đơn vị: fix k^6
// - 6 phép quay mặt 90°/270°: fix k^3
// - 3 phép quay mặt 180°: fix k^4
// - 8 phép quay đỉnh 120°/240°: fix k^2
// - 6 phép quay cạnh 180°: fix k^3
long long count_dice(int k, long long MOD) {
long long ans = 0;
ans = (power(k, 6, MOD) // 1 phép đơn vị
+ 6 * power(k, 3, MOD) // quay mặt 90°/270°
+ 3 * power(k, 4, MOD) // quay mặt 180°
+ 8 * power(k, 2, MOD) // quay đỉnh
+ 6 * power(k, 3, MOD)) // quay cạnh
% MOD;
return ans * power(24, MOD - 2, MOD) % MOD;
}
Định lý Polya (tổng quát hơn)
Polya mở rộng Burnside cho phép đếm theo trọng số. Với nhóm tác dụng lên tập vị trí , và tập màu :
Cycle index của :
trong đó = số chu trình độ dài trong hoán vị .
Số cấu hình với màu = thay .
// Cycle index của Z_n (nhóm quay n vị trí)
// Z(Z_n) = (1/n) * sum_{j=0}^{n-1} prod a_{d} với d = n/gcd(n,j), số lần = gcd(n,j)
// Thay a_i = m: Z = (1/n) * sum_{j=0}^{n-1} m^{gcd(n,j)}
// (trùng với công thức Burnside ở trên)
Ví dụ 3: Vòng chuỗi có lật (Dihedral group)
Nhóm đối xứng gồm xoay + lật (flip). Cần tính thêm phần cố định của phép lật:
long long count_bracelet(int n, int k, long long MOD) {
// n phép quay: sum k^{gcd(n,j)} / n (như trên)
long long ans = 0;
for (int j = 0; j < n; j++)
ans = (ans + power(k, __gcd(n, j == 0 ? n : j), MOD)) % MOD;
// n phép lật:
if (n % 2 == 0) {
// n/2 lật qua đỉnh: fix k^{n/2+1}
// n/2 lật qua cạnh: fix k^{n/2}
ans = (ans + n / 2 * power(k, n/2 + 1, MOD)) % MOD;
ans = (ans + n / 2 * power(k, n/2, MOD)) % MOD;
} else {
// n lật qua đỉnh: fix k^{(n+1)/2}
ans = (ans + n * power(k, (n+1)/2, MOD)) % MOD;
}
return ans * power(2 * n, MOD - 2, MOD) % MOD;
}
Công thức tổng quát
| Nhóm | Kích thước | Ứng dụng |
|---|---|---|
| (xoay) | Vòng chuỗi (necklace) | |
| (xoay + lật) | Vòng chuỗi có lật (bracelet) | |
| quay khối lập phương | Tô màu mặt/đỉnh xúc xắc | |
| Hoán vị bất kỳ | Mọi bài toán đếm đối xứng |
Khi nào dùng Burnside/Polya?
- Đếm cấu hình "phân biệt đến đối xứng": vòng chuỗi, đồ thị không nhãn, tô màu đa giác.
- Nhận ra dạng bài: "hai cấu hình giống nhau nếu có thể xoay/lật/hoán vị thành nhau".
- Khi đáp án lớn → tính mod nguyên tố (cần nghịch đảo ).
Bình luận