luogu P2257 YY的GCD
题面传送门
首先我们可以列出这个式子:\(\sum\limits_{k\in pr}^{n}{\sum\limits_{i=1}^{n}{\sum\limits_{j=1}^{m}{[gcd(i,j)==k]}}}\)
如果你仔细阅读了莫比乌斯反演的相关内容,你大概可以推到\(\sum\limits_{k\in pr}^{n}{\sum\limits_{d=1}^{n}{\mu(d)\times \lfloor \frac{n}{kd}\rfloor\times \lfloor \frac{m}{kd}\rfloor}}\)
这个东西看上去很难优化。
我们可以设\(T=kd\)
然后我们就有\(\sum\limits_{k\in pr}^{n}{\sum\limits_{d=1}^{n}{\mu(d)\times \lfloor \frac{n}{T}\rfloor\times \lfloor \frac{m}{T}\rfloor}}\)
然后可以枚举\(T\)就有\(\sum\limits_{T=1}^{n}{\lfloor \frac{n}{T}\rfloor\times \lfloor \frac{m}{T}\rfloor\times \sum\limits_{k\in pr,k|T}{\mu(\lfloor\frac{T}{k}\rfloor)}}\)
然后后面那个在线性筛的时候顺便处理一下就好了。每次询问整除分块即可。
时间复杂度\(O(n+T \sqrt n)\)
code:
#include<cstdio>
#define ll long long
#define min(a,b) ((a)<(b)?(a):(b))
using namespace std;
int n,m,k,T,flag[10000039],w=1e7,pr[10000039],ph,mu[10000039],f[10000039],cnt;
inline void swap(ll &x,ll &y){x^=y^=x^=y;}
int main(){
freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
register int i,j;register ll x,y,ans;
scanf("%d",&T);mu[1]=1;
for(i=2;i<=w;f[i]+=f[i-1],i++){
(!flag[i])&&(pr[++ph]=i,mu[i]=-1,f[i]=1);
for(j=1;j<=ph&&pr[j]*i<=w;j++){
flag[pr[j]*i]=1;
if(i%pr[j]==0){f[i*pr[j]]=mu[i];break;};
mu[i*pr[j]]=-mu[i];f[i*pr[j]]=-f[i]+mu[i];
}
}
while(T--){
scanf("%lld%lld",&x,&y);(x>y)&&(swap(x,y),0);ans=0;
for(i=1;i<=x;i=j+1)j=min(x/(x/i),y/(y/i)),ans+=(f[j]-f[i-1])*(x/i)*(y/i);printf("%lld\n",ans);
}
}