【Pólya定理】POJ2154-Color
题面
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 13906 Accepted: 4377
Description
Beads of N colors are connected together into a circular necklace of N beads (N<=1000000000). Your job is to calculate how many different kinds of the necklace can be produced. You should know that the necklace might not use up all the N colors, and the repetitions that are produced by rotation around the center of the circular necklace are all neglected.
You only need to output the answer module a given number P.
Input
The first line of the input is an integer X (X <= 3500) representing the number of test cases. The following X lines each contains two numbers N and P (1 <= N <= 1000000000, 1 <= P <= 30000), representing a test case.
Output
For each test case, output one line containing the answer.
Sample Input
5
1 30000
2 30000
3 30000
4 30000
5 30000
Sample Output
1
3
11
70
629
题意
\(n\)个珠子组成的项链,用\(n\)种颜色染色,能够组成多少种不同的项链。(旋转后相同算同一种项链) ,答案可能很大,请输出\(mod\) \(p\)后的结果。
第一行包含一个整数\(T(1≤T≤3500)\),表示\(T\)组数据。
接下来\(T\)行,每一行包含两个整数\(n,p(1≤n≤10^9, 1≤p≤30000)\)。
输出\(T\)行,每一行输出一个整数表示答案。
思路
循环同构,\(n\)范围很大不能直接莫反(\(O(n)\)),必须枚举值因子用欧拉函数优化,其次已知公式和前置知识,代入
复杂度\(O(\sqrt n)\)
前置知识
群论,二元关系(不做解释)
Pólya定理
集合X可以看成是集合\(A=\{a_1,a_2,...a_n\}\)的每个元素赋予式样(颜色,种类等)的映射的集合,引入式样的集合\(B\),令\(X=\{f|f:A\rightarrow B\}\)记为\(B^A\)
\(G\)在\(B^A\)上的作用:\(A\)上的置换群\(G\)到集合\(B^A\)的作用为\(g(f):a\rightarrow f(g(a))\)
式样清单:\(G\)作用在\(B^A\)上的\(G-\)轨道的集合
\(B^A\)关于\(G\)的式样清单记为\(F\)则\(\sum_{f\in F}w(f)=P_G(\sum_{b\in B}w(b),\sum_{b\in B}w(b)^2,...,\sum_{b\in B}w(b)^n)\)
(计数时候权值都是1,有时候可以把权值b变成一个变量,给一个不定元,代入可得生成函数,记录每个元用了多少次)
简化版:
\(B^A\)关于\(G\)的式样清单记为\(F\),则\(|F|=P_G(|B|,|B|,...,|B|)\)
Burnside引理
设有限群\((G,o)\)作用在有限集\(X\)上,则\(X\)上的\(G-\)轨道数量为\(N=\frac{1}{G}\sum_{g\in G}\psi(g)\),其中\(\psi(g)\)表示\(g(x) = x\)的\(x\)的数量
置换群的轮换指标:
设\((G,o)\)是一个\(n\)元置换的置换群,它的轮换指标为:
\(P_G(x_1,x_2,...,x_n)=\frac{1}{|G|}\sum_{g\in G}x_1^{b_1}x_2^{b_2}...x_n^{b_n}(b关于g)\)
正n边形的旋转群的轮换指标:
\(P_G=\frac{1}{n}\sum_{d|n}\phi(d)x_d^{n/d}\)
正n边形的二面体群的轮换指标(运用于对称轴翻转,这个证明我记不住):
\(P_G=\frac{1}{2n}\sum_{d|n}\phi(d)x_d^{n/d}+\begin{cases} \frac{1}{2}x_1x_2^{\frac{n-1}{2}},& \text{n is odd} \\ \frac{1}{4}(x_2^{\frac{n}{2}}+x_1^2x_2^{\frac{n-2}{2}}), & \text{n is even} \end{cases}\)
例题通用:给\(n\)元环的节点涂上颜色,有\(m\)种颜色,通过旋转可以得到的方案算同一种方案,求方案数
令\(X=\{x|x:\{a_i,...a_n\}\rightarrow\{b_1,...b_m\}\}\),\(G\)是\(n\)个置换组成的\(n\)边形的旋转群,其第\(i(0≤i≤n)\)个元素是\(g_i = [i + 1,i + 2...n,1,...i]\)。
则答案为\(N=\frac{1}{n}\sum_{i=0}^{n-1}\psi(gi)\)
\(\psi(g_i)=m^{gi的环数量}\):有多少染色方案\(x\),在\(g_i\)作用下保持不变
\(g_0 = e = [1,2...n],\psi(e)=m^n\)
\(g_1 = [2,3...n,1],\psi(g1)=m^1\)
\(g_2 = [3,4...n,1,1],\psi(g2)=m^2\)
推导易知\(\psi(g_i)=m^{gcd(n,i)}\)
所以\(N=\frac{1}{n}\sum_{i=0}^{n-1}m^{gcd(n,i)}=\frac{1}{n}\sum_{d|n}\phi(d)m^{n/d}\)(欧拉函数,直接枚举,答案和莫反一样,但是时间更加优化了)
关于正方体的一些置换群(别的置换群,套路基本一致)
顶点置换群:
\(P_G=\frac{1}{24}(x_1 ^ 8 + 8x_1^{2}x_3^{2}+9x_2^4+6x_4^2)\)
边置换群:
\(P_G=\frac{1}{24}(x_1 ^ {12} +8x_3^4+ 6x_1x_2^{5}+3x_2^6+6x_4^3)\)
面置换群:
\(P_G=\frac{1}{24}(x_1^{12} +8x_3^2+6x_2^3+ 3x_1^{2}x_2^{2}+6x_1^{2}x_4)\)
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
typedef long long ll;
const int N = 1e6 + 100;
int t, n, m, p;
int quickpow(int a, int b) {//快速幂
int res = 1;
while (b > 0) {
if (b & 1) res = res * a % p;
b >>= 1;
a = a * a % p;
}
return res;
}
int euler_function(int x) {//欧拉函数
int ans = x;
for (int i = 2; i * i <= x; i++) {
if (x % i == 0) {
ans = ans / i * (i - 1);//multiply
while (x % i == 0) x /= i;
}
}
if (x > 1) ans = ans / x * (x - 1);
return (ans + p) % p;
}
void solve() {
cin >> n >> p;
int ans = 0;
for (int i = 1; i * i <= n; i++) {
if (i * i == n) ans = (ans + quickpow(n, i - 1) * euler_function(i) % p + p) % p;
else if (n % i == 0) ans = (ans + quickpow(n, i - 1) * euler_function(n / i) % p + quickpow(n, (n / i - 1)) * euler_function(i) % p + p) % p;
}
cout << (ans + p) % p << endl;
return;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
while (cin >> t) {
while (t--) {
solve();
}
}
return 0;
}