题链:
http://www.lydsy.com/JudgeOnline/problem.php?id=2693
题解:
莫比乌斯反演
先看看这个题,BZOJ 2154 Crash的数字表格,本题的升级版:改为了多组数据。
既然是多组数据,那么之前的$O(N)$的方法就不行了。
现在需要对求ANS的式子进行优化,看看能不能降低复杂度。
$ANS=sum_{g=1}^{min(n,m)}g imes sum_{d=1}^{min(lfloor frac{n}{g} floor,lfloor frac{m}{g} floor)} mu(d)d^2sum(lfloor frac{n}{gd} floor,lfloor frac{m}{gd} floor)$
令$D=gd$,然后去枚举D,则
$quadquad=sum_{D=1}^{min(n,m)}sum(lfloor frac{n}{D} floor,lfloor frac{m}{D} floor) sum_{d|D} frac{D}{d}mu(d)d^2$
$quadquad=sum_{D=1}^{min(n,m)}sum(lfloor frac{n}{D} floor,lfloor frac{m}{D} floor) sum_{d|D} dD imesmu(d)$
令$w[D]=sum_{d|D} dD imesmu(d)$,所以
$ANS=sum_{D=1}^{min(n,m)}sum(lfloor frac{n}{D} floor,lfloor frac{m}{D} floor) w[D]$
如果可以求出$w[D]$的值,那么这个求ANS的式子就可以用上向下取整的特性,以$O(sqrt N)$的复杂度求出。
而至于$w[D]$求法,注意到这个也是积性函数,可以在线性筛时求出:
1.对于一个质数p,$w[p]=1 imes p imes 1+p imes p imes(-1)$
2.对于枚举到的i和质数p,
如果i%p!=0,则运用积性函数的性质:$w[i imes p]=w[i] imes w[p]$
否则,不难发现,新增的p导致产生的其他加项中$mu(d)=0$,所以直接$w[i imes p]=w[i] imes p$
(w[ ]的推导仔细想想哈,其实并不麻烦的)
代码:
#include<cstdio> #include<cstring> #include<iostream> #define MAXN 10000050 using namespace std; const int mod=100000009; int w[MAXN],pw[MAXN]; void Sieve(){ static bool np[MAXN]; static int prime[MAXN],pnt; w[1]=1,pw[1]=1; for(int i=2;i<=10000000;i++){ if(!np[i]) prime[++pnt]=i,w[i]=((1ll*i-1ll*i*i%mod)%mod+mod)%mod; for(int j=1;j<=pnt&&i<=10000000/prime[j];j++){ np[i*prime[j]]=1; if(i%prime[j]) w[i*prime[j]]=((-1ll*w[i]*prime[j]%mod*prime[j]%mod+mod)%mod+1ll*w[i]*prime[j]%mod)%mod; else{w[i*prime[j]]=1ll*w[i]*prime[j]%mod; break;} } pw[i]=(1ll*pw[i-1]+w[i])%mod; } } int sum(int n,int m){ return ((1ll*(1+n)*n/2%mod)*(1ll*(1+m)*m/2%mod))%mod; } int main(){ Sieve(); int Case,n,m,ans,mini; scanf("%d",&Case); for(int i=1;i<=Case;i++){ scanf("%d%d",&n,&m); ans=0; mini=min(n,m); for(int d=1,last;d<=mini;d=last+1){ last=min(n/(n/d),m/(m/d)); ans=(1ll*ans+1ll*(pw[last]-pw[d-1]+mod)%mod*sum(n/d,m/d)%mod)%mod; } printf("%d ",(ans+mod)%mod); } return 0; }