B
u
r
n
S
i
d
e
BurnSide
BurnSide 引理:
∣
X
/
G
∣
=
1
∣
G
∣
∑
g
∈
G
∣
X
g
∣
|X/G|=\frac{1}{|G|}\sum_{g\in G}|X^g|
∣X/G∣=∣G∣1g∈G∑∣Xg∣ 正规表述:轨道数
=
=
= 被
G
G
G 中一个元素保持不动的点的个数的平均值 见:百度百科
由于我们太难把所有的置换等价操作给求出来(太多了…) 故有更优化的
P
o
l
y
a
Polya
Polya 定理 它的关键就是给出计算不动点的个数的方法
P
o
l
y
a
Polya
Polya 定理:
A
n
s
=
1
∣
G
∣
∑
g
∈
G
m
c
(
g
)
Ans=\frac{1}{|G|}\sum_{g\in G}m^{c(g)}
Ans=∣G∣1g∈G∑mc(g) 表述:对于有
m
m
m 种颜色染色的问题,
∣
X
g
∣
=
m
c
(
g
)
|X^g|=m^{c(g)}
∣Xg∣=mc(g) 其中
c
(
g
)
c(g)
c(g) 表示在置换
g
g
g 的情况下,不动点的个数
我们直接使用
P
o
l
y
a
Polya
Polya 定理,对于本质相同的操作,只有旋转操作 旋转操作有
n
n
n 种,就是顺时针旋转
(
0
∼
n
−
1
)
(0\sim n-1)
(0∼n−1) 个珠子 ,当然也可以写成旋转
(
1
∼
n
)
(1\sim n)
(1∼n) 个珠子
考虑,如果我们顺时针旋转
k
k
k 个珠子,会获得多少个不动点 根据我们的数学知识,答案为
gcd
(
k
,
n
)
\gcd(k,n)
gcd(k,n) 那么答案就是
A
n
s
=
1
∣
n
∣
∑
k
=
1
n
n
gcd
(
k
,
n
)
Ans=\frac{1}{|n|}\sum_{k=1}^n n^{\gcd(k,n)}
Ans=∣n∣1k=1∑nngcd(k,n)
考虑到
n
n
n 非常大,我们不能直接枚举,我们像做莫比乌斯反演一样,套路化做:
A
n
s
=
1
n
∑
d
∣
n
n
d
∑
i
=
1
n
[
gcd
(
k
,
n
)
=
d
]
=
1
n
∑
d
∣
n
n
d
∑
i
=
1
⌊
n
d
⌋
[
gcd
(
k
,
n
d
)
=
1
]
=
1
n
∑
d
∣
n
n
d
×
φ
(
n
d
)
\begin{aligned} Ans&=\frac{1}{n}\sum_{d|n}n^d\sum_{i=1}^n\Big[ \gcd(k,n)=d \Big]\\ &=\frac{1}{n}\sum_{d|n}n^d\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\Big[ \gcd(k,\frac{n}{d})=1 \Big]\\ &=\frac{1}{n}\sum_{d|n}n^d\times\varphi(\frac{n}{d}) \end{aligned}
Ans=n1d∣n∑ndi=1∑n[gcd(k,n)=d]=n1d∣n∑ndi=1∑⌊dn⌋[gcd(k,dn)=1]=n1d∣n∑nd×φ(dn)
暴力枚举,时间复杂度为
O
(
T
×
n
3
/
4
)
O(T\times n^{3/4})
O(T×n3/4),差不多也能过
代码
#include<bits/stdc++.h>#define IOS ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
using namespace std;typedeflonglong ll;voidshow(){std::cerr << endl;}template<typename T,typename... Args>voidshow(T x,Args... args){std::cerr <<"[ "<< x <<" ] , ";show(args...);}constint MAX =2e5+50;constint MOD =1e9+7;constint INF =0x3f3f3f3f;const ll LINF =0x3f3f3f3f3f3f3f3f;constdouble EPS =1e-5;
ll qpow(ll a,ll n){/* */ll res =1LL;while(n){if(n&1)res=res*a%MOD;a=a*a%MOD;n>>=1;}return res;}
ll qpow(ll a,ll n,ll p){a%=p;ll res =1LL;while(n){if(n&1)res=res*a%p;a=a*a%p;n>>=1;}return res;}
ll npow(ll a,ll n){/* */ll res =1LL;while(n){if(n&1)res=res*a;a=a*a;n>>=1;if(res<0||a<0)return0;}return res;}
ll inv(ll a){/* */returnqpow(a,MOD-2);}
ll inv(ll a,ll p){returnqpow(a,p-2,p);}
ll phi(ll n){
ll res = n;for(int i =2;i * i <= n;++i){if(n % i ==0){
res = res *(1-inv(i)+ MOD)% MOD;while(n % i ==0)n /= i;}}if(n >1)res = res *(1-inv(n)+ MOD)% MOD;return(res + MOD)% MOD;}intmain(){
IOS;int T;cin >> T;while(T--){int n;cin >> n;
ll res =0;for(int i =1;i * i <= n;++i){if(n % i ==0){
res =(res +qpow(n,i)*phi(n / i)% MOD)% MOD;if(i * i != n)res =(res +qpow(n,n/i)*phi(i)% MOD)% MOD;}}
res = res *inv(n)% MOD;
cout << res << endl;}return0;}