【模板】Polya 定理/Burnside 引理
Polya 定理
给定一个\(n\)个点,\(n\)条边的环,有\(n\)种颜色,给每个顶点染色,问有多少种本质不同的染色方案,答案对\(10^9+7\)取模
注意本题的本质不同,定义为:只需要不能通过旋转与别的染色方案相同。
一种染色方案可以看做先染了前\(d\)个位置,然后将这一段复制\(\frac{n}{d}\)次拼接而成,其中\(d|n\)。我们称这个\(d\)为一种染色方案的周期(这里默认是最小正周期)。
对于一个周期(循环个数)为\(d\)的染色方案,将它旋转\(d\)次会得到\(d\)个看起来不同但本质相同的染色方案。
设\(f(x)\)表示周期为\(x\)的看上去不同的方案数。枚举周期\(d\),那么每一种周期的方案就多算\(d\)次,因此\(ans=\sum\limits_{d|n}\dfrac{f(d)}{d}\)
\(f(x)\)不容易计算,但是我们知道:对于\(n\)的所有约数\(d\),将\(f(d)\)求和就会得到总方案数\(m^n\),即
\[m^n=\sum\limits_{d|n}f(d)
\]
莫比乌斯反演得
\[f(x)=\sum\limits_{d|x}\mu(\frac{n}{d})m^d
\]
代入第一个式子得到
\[ans=\sum\limits_{d|n}\frac{1}{d}\sum\limits_{k|d}\mu(\frac{d}{k})m^k
\]
\[=\sum\limits_{d|n}\frac{d}{n}\sum\limits_{k|\frac{n}{d}}\mu(\frac{n}{dk})m^k
\]
\[=\frac{1}{n}\sum\limits_{d|n}d\sum\limits_{k|\frac{n}{d}}\mu(\frac{n}{dk})m^k
\]
\[=\frac{1}{n}\sum\limits_{k|n}m^k\sum\limits_{d|\frac{n}{k}}d\mu(\frac{n}{dk})
\]
\[=\frac{1}{n}\sum\limits_{k|n}m^k\varphi(n/k)
\]
上面设颜色的数量为\(m\)是为了避免混淆,本题中\(m=n\)。
Code
#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7;
int t, n, m;
unordered_map < int, int > fphi;
int read()
{
int x = 0, fl = 1; char ch = getchar();
while (ch < '0' || ch > '9') { if (ch == '-') fl = -1; ch = getchar();}
while (ch >= '0' && ch <= '9') {x = x * 10ll + ch - '0'; ch = getchar();}
return x * fl;
}
int qpow(int base, int pw)
{
int s = 1;
while (pw)
{
if (pw & 1) s = 1ll * s * base % mod;
base = 1ll * base * base % mod;
pw >>= 1;
}
return s;
}
int phi(int x)
{
if (fphi[x]) return fphi[x];
int t = x, y = x;
for (int i = 2; i <= m; i ++ )
{
if ((x % i) == 0)
{
t = t / i * (i - 1);
while ((x % i) == 0) x /= i;
}
}
if (x > 1) t = t / x * (x - 1);
return fphi[y] = t;
}
int main()
{
t = read();
while (t -- )
{
n = read(), m = (int)(sqrt(n));
int res = 0;
for (int k = 1; k <= m; k ++ )
{
if (n % k) continue;
res = (res + 1ll * qpow(n, k) * phi(n / k) % mod) % mod;
if (k * k != n) res = (res + 1ll * qpow(n, n / k) * phi(k) % mod) % mod;
}
res = 1ll * res * qpow(n, mod - 2) % mod;
printf("%d\n", res);
}
return 0;
}
Burnside 引理
本质不同的方案数为在每个置换下稳定不动的方案的总和(不动点数目之和)除以总置换数。
注意必须要满足群存在逆元、单位元,且具有封闭性。