【题意】
(x) 组数据
每组询问 (n) 个颜色填涂 (n) 个空位的环,问不同构方案数,答案对 (p) 取模。
规定某个环能被另一个环旋转得到时,这两个环同构。
(xleq 3500, nleq 10^9)
【分析】
显然 (n) 个角度的旋转构成一个群,根据 polya 定理,得到答案为:
(displaystyle {1over n}sum_{i=1}^n n^{gcd(i, n)}={1over n}sum_{dmid n} n^d oldsymbol varphi({nover d})=sum_{dmid n} n^{d-1} oldsymbol varphi({nover d}))
但如果暴力计算每一个 (oldsymbol varphi({nover d})) 复杂度为 (O(n^{3over 4})) 可能不够,考虑先打出前 ({n^{3over 5}}) 个欧拉函数值,则求解所有欧拉函数的复杂度降低为 (O(n^{3over 5}))(证明如下)
故求解一组的复杂度为 (O(n^{3over 5})+O(sqrt n)+O(sqrt nlog n)=O(n^{3over 5})),总复杂度即为 (O(xcdot n^{3over 5})),卡卡常能过
【代码】
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> pii;
typedef double db;
#define fi first
#define se second
int n, mod;
inline int fpow(int a,int x) { ll ans=1; for(;x;x>>=1,a=(ll)a*a%mod) if(x&1) ans=(ll)ans*a%mod; return ans; }
const int Lim=2.6e5, MAXN=Lim+10;
int fc[MAXN], phi[MAXN], prime[MAXN], cntprime;
inline int getphi(int n) {
if(n<=Lim) return phi[n];
int val=n;
for(int j=1;j<=cntprime;++j)
if((ll)prime[j]*prime[j]>n) break;
else if(n%prime[j]==0){
val=val/prime[j]*(prime[j]-1);
while(n%prime[j]==0) n/=prime[j];
}
if(n!=1) val=val/n*(n-1);
return val;
}
inline int ans(){
int res=0;
for(int i=1;i*i<=n;++i) if(n%i==0) {
int j=n/i;
res+=(ll)getphi(j)*fpow(n, i-1)%mod;
res-=(res>=mod?mod:0);
if(i!=j){
res+=(ll)getphi(i)*fpow(n, j-1)%mod;
res-=(res>=mod?mod:0);
}
}
return res;
}
inline void sieve(){
phi[1]=1;
for(int i=2;i<=Lim;++i){
if(!fc[i]) fc[i]=prime[++cntprime]=i, phi[i]=i-1;
for(int j=1;j<=cntprime;++j)
if(prime[j]*i>Lim||prime[j]>fc[i]) break;
else fc[prime[j]*i]=prime[j], phi[prime[j]*i]=phi[i]*(prime[j]-(prime[j]!=fc[i]));
}
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
sieve();
int x; cin>>x;
while(x--&&cin>>n>>mod) cout<<ans()<<"
";
cout.flush();
return 0;
}
【证明】
朴素求解所有欧拉函数的复杂度求解如下考虑:
由于每个数字 (n) ,设其存在一个严格小于 (sqrt n) 的因数 (d) ,则必然同时存在一严格大于 (sqrt n) 的因数 ({nover d})
故因数个数至多为 (2cdot(sqrt n-1)+1=2sqrt n-1)
我们朴素求解 (n) 的欧拉函数值,复杂度为 (O(sqrt n))
(displaystyle T(n)=sum_{dmid n}Ccdot sqrt dleq Csum_{d=1}^{sqrt n}(sqrt d+sqrt {nover d}))
由于 (displaystyle sum_{x=1}^{sqrt n} sqrt xapprox int_1^{sqrt n}x^{1over 2} ext dx={2over 3}(x^{3over 2}|^{sqrt n}_1)=O(n^{3over 4}))
且 (displaystyle sum_{x=1}^{sqrt n} {1over sqrt x}approx int_1^{sqrt n} x^{-{1over 2}} ext dx=2(x^{1over 2}|^{sqrt n}_1)=O(n^{1over 4}))
故 (T(n)=Ccdot O(n^{3over 4})+Ccdot sqrt ncdot O(n^{1over 4})=O(n^{3over 4}))
此为朴素计算的复杂度
考虑有限筛出 (m) 范围内欧拉函数的值,由上述朴素的分析得到:
若 (m<sqrt n) ,则前半部分时间复杂度减小,后半部分不变,总复杂度为 (O(m)+o(n^{3over 4})+O(n^{3over 4})=O(n^{3over 4}))
故 (mgeq sqrt m),此时可得,后半部分的因数均大于 (m),故其对应的小因数均小于 ({nover m})
故复杂度化为 (displaystyle T(n)=O(m)+sum_{i=1}^{nover m}Ccdot sqrt{nover i}=O(m)+Ccdot sqrt ncdot O(({nover m})^{1over 4})=O(m)+O({n^{3over 4}over m^{1over 4}}))
设 (displaystyle T(n)=C_1m+C_2cdot {n^{3over 4}over m^{1over 4}})
根据均值不等式,(displaystyle C_1m=C_2cdot {n^{3over 4}over m^{1over 4}}) 时 (T(n)) 取最小值,达到 (O(m))
求解等式得到 (m=({C_2over C_1})^{4over 5}cdot n^{3over 5})
由于我也不知道 (C_1, C_2) 的值,故均取 (1),得到 (T(n)=O(m)=O(n^{3over 5}))