正题
题目链接:https://www.luogu.com.cn/problem/P2257
题目大意
给出n,mn,mn,m,求∑i=1n∑j=1m[gcd(i,j)∈p]\sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)\in p]i=1∑nj=1∑m[gcd(i,j)∈p]
定义ppp是质数集
解题思路
首先考虑定义f(x)=∑i=1n∑j=1m[gcd(i,j)==x]f(x)=\sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)==x]f(x)=i=1∑nj=1∑m[gcd(i,j)==x]
然后有F(x)=∑d∣xf(x)=⌊nx⌋⌊mx⌋F(x)=\sum_{d|x}f(x)=\lfloor\frac{n}{x}\rfloor\lfloor\frac{m}{x}\rfloorF(x)=∑d∣xf(x)=⌊xn⌋⌊xm⌋
根据莫比乌斯反演就有f(d)=∑i∣dμ(id)F(d)f(d)=\sum_{i|d}\mu(\frac{i}{d})F(d)f(d)=i∣d∑μ(di)F(d)即f(d)=∑i∣dμ(id)⌊nx⌋⌊mx⌋f(d)=\sum_{i|d}\mu(\frac{i}{d})\lfloor\frac{n}{x}\rfloor\lfloor\frac{m}{x}\rfloorf(d)=i∣d∑μ(di)⌊xn⌋⌊xm⌋枚举质数ppp
然后有ans=∑pn∑d=1nμ(d)⌊npd⌋⌊mpd⌋ans=\sum_{p}^{n}\sum_{d=1}^{n}\mu(d)\lfloor\frac{n}{pd}\rfloor\lfloor\frac{m}{pd}\rfloorans=p∑nd=1∑nμ(d)⌊pdn⌋⌊pdm⌋
⇒ans=∑in⌊ni⌋⌊mi⌋∑d∣iμ(id)\Rightarrow ans=\sum_{i}^{n}\lfloor \frac{n}{i}\rfloor\lfloor \frac{m}{i}\rfloor\sum_{d|i}\mu(\frac{i}{d})⇒ans=i∑n⌊in⌋⌊im⌋d∣i∑μ(di)
预处理∑d∣iμ(id)\sum_{d|i}\mu(\frac{i}{d})∑d∣iμ(di)的前缀和即可。
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e7+10;
int T,n,m,cnt;
int pri[N],mu[N],g[N];
long long ans;
bool vis[N];
void prime(){mu[1]=1;for(int i=2;i<N;i++){if(!vis[i])mu[i]=-1,pri[++cnt]=i;for(int j=1;j<=cnt&&pri[j]*i<N;j++){vis[i*pri[j]]=1;if(i%pri[j]==0)break;mu[i*pri[j]]=-mu[i];}}for(int j=1;j<=cnt;j++)for(int i=1;pri[j]*i<N;i++)g[i*pri[j]]+=mu[i];for(int i=1;i<N;i++)g[i]+=g[i-1];return;
}
int main()
{prime();scanf("%d",&T);while(T--){scanf("%d%d",&n,&m);if(n>m)swap(n,m);ans=0;for(int l=1,r;l<=n;l=r+1){r=min(n/(n/l),m/(m/l));ans+=1ll*(n/l)*(m/l)*(g[r]-g[l-1]);}printf("%lld\n",ans);}
}