莫比乌斯反演
坑先留着,noip之后再补
PoPoQQQ的课件
证明
例题
[luogu2257]YY的GCD
peng-ym的blog
跟着推了一遍,觉得好妙
#include<bits/stdc++.h>
#define N 10000002
using namespace std;
inline void read(int &x){
x=0;char c=getchar();int p=1;
while(!isdigit(c)){if(c=='-')p=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c-48);c=getchar();}
x*=p;
}
typedef long long ll;
inline void print(ll x){
int cnt=0,a[15];
do{a[++cnt]=x%10,x/=10;}while(x);
for(int i=cnt;i>=1;i--)putchar(a[i]+'0');
puts("");
}
bool vis[N];
ll sum[N];
int cnt,prim[N],mu[N],g[N];
inline void get_mu(int n){
mu[1]=1;
for(int i=2;i<=n;i++){
if(!vis[i])mu[i]=-1,prim[++cnt]=i;
for(int j=1;j<=cnt&&prim[j]*i<=n;j++){
vis[i*prim[j]]=1;
if(i%prim[j]==0)break;else mu[prim[j]*i]=-mu[i];
}
}
for(int j=1;j<=cnt;j++)for(int i=1;i*prim[j]<=n;i++)g[i*prim[j]]+=mu[i];
for(int i=1;i<=n;i++)sum[i]=sum[i-1]+1ll*g[i];
}
int n,m;
int main(){
int t;read(t);
get_mu(10000000);
while(t--){
read(n);read(m);
if(n>m)swap(n,m);
ll 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)*(sum[r]-sum[l-1]);
}
print(ans);
}
return 0;
}