[2020HDU多校第九場][HDU 6868][B. Absolute Math]
又被學弟們爆錘了TAT感覺可以原地退役了_(:з」∠)_
題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=6868
題目大意:設\(f(n)=\sum_{d|n} |\mu(d)|\),求\(\sum_{i=1}^{m} f(ni)\)
題解:分析\(f(n)\)的性質,設\(n=\prod_{i=1}^{k} p_i^{q_i}\),\(\omega = \prod_{i=1}^{k} p_i \),顯然當且僅當\(d|\omega\)時存在貢獻,而這樣的\(d\)一共有\(2^k\)個。故若我們設\(k(n)\)為\(n\)的不同質因子個數,則\(f(n)=2^{k(n)}\),是一個積性函式
由於\(k(n)=k(\omega)\),所以有\(f(n)=f(\omega)\),進一步地我們可以得出,\(\sum_{i=1}^{m} f(ni)=\sum_{i=1}^{m} f(\omega i)\)。令\(S(n,m)=\sum_{i=1}^{m} f(ni)\),則有\(S(n,m)=S(\omega,m)\)
注意到\(\omega\)是不同質數的乘積,因此\(f(\omega i)=f(i)\cdot f(\frac{\omega}{gcd(i,\omega)})\),就有$$S(n,m)=S(\omega,m)=\sum_{i=1}^{m} f(\omega i)=\sum_{i=1}^{m} f(i)\cdot f(\frac{\omega}{gcd(i,\omega)})$$
列舉\(d=gcd(i,\omega)\),得到$$S(\omega,m)=\sum_{d|\omega}f(\frac{\omega}{d})\sum_{i=1}^{\lfloor \frac{m}{d} \rfloor}f(id)[gcd(i,\frac{\omega}{d})=1]$$
由\(\sum_{d|n}\mu(d)=[n==1]\)$$S(\omega,m)=\sum_{d|\omega}f(\frac{\omega}{d})\sum_{i=1}^{\lfloor \frac{m}{d} \rfloor}f(id)\sum_{e|gcd(i,\frac{\omega}{d})}\mu(e)$$
交換求和次序,則答案為$$\sum_{d|\omega}f(\frac{\omega}{d})\sum_{e|\frac{\omega}{d}}\mu(e)\sum_{i=1}^{\lfloor \frac{m}{de} \rfloor}f(ide)$$
設\(T=d\cdot e\),則有\(T|\omega\),再次交換求和次序,得出答案為$$\sum_{T|\omega}\sum_{i=1}^{\lfloor \frac{m}{T} \rfloor}f(iT)\sum_{d|T}\mu(d)f(\frac{\omega}{\frac{T}{d}})=\sum_{T|\omega}S(T,\lfloor \frac{m}{T} \rfloor)\sum_{d|T}\mu(d)f(d\cdot \frac{\omega}{T})$$
再次注意到\(\omega\)是不同質數的乘積,因此有對任意\(T|\omega\),\(gcd(T,\frac{\omega}{T})=1\),而由於\(d|T\),故\(f(d\cdot \frac{\omega}{T})=f(d)f(\frac{\omega}{T})\),因此有$$S(\omega,m)=\sum_{T|\omega}S(T,\lfloor \frac{m}{T} \rfloor)\sum_{d|T}\mu(d)f(d)f(\frac{\omega}{T})=\sum_{T|\omega}f(\frac{\omega}{T})S(T,\lfloor \frac{m}{T} \rfloor)\sum_{d|T}\mu(d)f(d)$$
其中\(f\)的值可以\(O(n)\)線性篩預處理,\(S\)可以遞迴求解,現在問題就在於求\(\sum_{d|T}\mu(d)f(d)\)的值
注意到這邊\(T\)也是若干個不同質數的乘積,而\(f(d)=2^{k(d)}, \mu(d)=(-1)^{k(d)}\),考慮對所有相同的\(k\)進行求和,則有\(\sum_{d|T}\mu(d)f(d)=\sum_{i=0}^{k(T)}C_{k(T)}^{i}2^i\cdot(-1)^i\),發現這是一個二項式展開的形式,故有\(\sum_{d|T}\mu(d)f(d)=(2+(-1))^{k(T)}=(-1)^{k(T)}=\mu(T)\),於是我們就得出了最終的式子$$S(n,m)=S(\omega,m)=\sum_{T|\omega}\mu(T)f(\frac{\omega}{T})S(T,\lfloor \frac{m}{T}\rfloor)$$
得到這個式子後直接遞迴求解即可,最壞情況下\(n\)是等於最小的八個質數的乘積\(9699690\),這種情況下也只會遍歷到\(256\)個不同的\(S(n,m)\),賽中直接交跑了不到三秒就過了,賽後再交發現會TLE,可能還需要些常數優化_(:з」∠)_(賽中賽後執行時間差了整整一倍可還行)
#include<bits/stdc++.h> using namespace std; #define N 10000001 #define MOD 1000000007 int T,n,f[N],sf[N],mu[N],v[N],p[N],cnt; void pretype() { v[1]=f[1]=mu[1]=1; for(int i=2;i<N;i++){ if(!v[i]){p[++cnt]=i,mu[i]=-1,f[i]=2,v[i]=i;} for(int j=1;j<=cnt && 1ll*i*p[j]<N;j++){ v[i*p[j]]=v[i]*p[j]; if(i%p[j]==0){f[i*p[j]]=f[i],v[i*p[j]]=v[i];break;} mu[i*p[j]]=-mu[i]; f[i*p[j]]=2*f[i]; } } for(int i=1;i<N;i++)sf[i]=(sf[i-1]+f[i])%MOD; } int S(int n,int m) { if(m==0)return 0; if(m==1)return f[n]; if(n==1)return sf[m]; int res=0; for(int d=1;d*d<=n;d++)if(n%d==0){ res=(res+MOD+1ll*f[n/d]*S(d,m/d)%MOD*mu[d])%MOD; res=(res+MOD+1ll*f[d]*S(n/d,m/(n/d))%MOD*mu[n/d])%MOD; } return res; } int main() { int T,n,m; pretype(); scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); printf("%d\n",S(v[n],m)); } }View Code