简单的写一下吧,Polya定理就是用来求等价类的数目的。
什么是等价类?经过某些置换操作能相等的两个的状态属于同一个等价类。
然后是一些基本的定理,
等价类的数目(C)为置换群的不动点的平均值,
即(C=frac{1}{|G|}sum _{fin G}k^{m(f)})
其中,(G)为置换群,(f)为其中的一种置换,(m(f))表示把置换(f)看成(m(f))个(f)的乘积(可以理解为循环节),(k)表示颜色的种类数。
显然本题的置换群就是({旋转0个,旋转1个,...,旋转n个})
考虑旋转(k)个的循环节(p),显然(p|k),同时(p|n),所以旋转(k)个的贡献就是(n^{gcd(k,n)})
那么最终答案就是(frac{1}{n}sum_{i=0}^{n-1}n^{gcd(i,n)})
直接求显然是(O(nlogn))的
设(n)的约数为(m)个,考虑到不同(gcd)的数量只有(m)个,于是枚举约数(d),
令(k=e*d),显然满足(gcd(k,n)=d)的(e)要与(frac{n}{d})互质,那么这样的(k)有(varphi{frac{n}{d}})个
于是最终答案就是(frac{1}{n}sum_{d|n}n^dvarphi{frac{n}{d}})
#include <bits/stdc++.h>
using namespace std;
const int MOD = 1e9 + 7;
int T, n;
int gcd(int a, int b){
return !b ? a : gcd(b, a % b);
}
long long ans;
long long fast_pow(long long a, int k){
long long ans = 1;
while(k){
if(k & 1) ans = ans * a % MOD;
a = a * a % MOD; k >>= 1;
}
return ans;
}
int phi(int x){
if(x == 1) return 1;
int y = x;
int p = sqrt(x);
for(int i = 2; i <= p && x != 1; ++i)
if(x % i == 0){
y = y / i * (i - 1);
while(x % i == 0) x /= i;
}
if(x != 1) y = y / x * (x - 1);
return y;
}
int main(){
scanf("%d", &T);
while(T--){
scanf("%d", &n); ans = 0;
int p = sqrt(n);
for(int i = 1; i <= p; ++i)
if(n % i == 0){
ans = (ans + fast_pow(n, i) * phi(n / i)) % MOD;
if(i * i != n) ans = (ans + fast_pow(n, n / i) * phi(i)) % MOD;
}
printf("%lld
", ans * fast_pow(n, MOD - 2) % MOD);
}
return 0;
}