没有权限号挂氵谷传送门
【题目分析】
很明显,题目要求求的是这个式子:
所以先考虑一个素数怎么求,当然很简单了:
接下来令:
我们要求的式子就是
所以可以得到:
反演:
又因为有
所以
最后这个神仙式子有两项dp,所以感觉化不动了,但其实换个元就行了,令T=dp
交换一下枚举顺序:
现在就比较明显了,后面的sigma直接上整除分块即可,所以考虑如何线性筛前面这个式子。
首先预处理出1~1e7的mu,然后直接枚举倍数更新就行了。
(写数论博客好累qwq)
【代码~】
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN=1e7+10;
int T,N;
int n,m,up;
int prime[MAXN],vis[MAXN],tot;
int mu[MAXN];
LL sum[MAXN],seg[MAXN];
LL ans;
int Read(){
int i=0,f=1;
char c;
for(c=getchar();(c>'9'||c<'0')&&c!='-';c=getchar());
if(c=='-')
f=-1,c=getchar();
for(;c>='0'&&c<='9';c=getchar())
i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
void pre(){
mu[1]=1;
for(int i=2;i<=1e7;++i){
if(!vis[i])
prime[++tot]=i,mu[i]=-1;
for(int j=1;j<=tot&&prime[j]*i<=1e7;++j){
vis[i*prime[j]]=1;
if(i%prime[j]==0)
break;
mu[i*prime[j]]=-mu[i];
}
}
for(int i=1;i<=tot;++i){
for(int j=1;j*prime[i]<=1e7;++j){
seg[j*prime[i]]+=mu[j];
}
}
for(int i=1;i<=1e7;++i)
sum[i]=sum[i-1]+seg[i];
}
int main(){
T=Read();
pre();
while(T--){
ans=0;
n=Read(),m=Read();
N=min(n,m);
for(int i=1;i<=N;i=up+1){
up=min(n/(n/i),m/(m/i));
ans+=(sum[up]-sum[i-1])*(n/i)*(m/i);
}
cout<<ans<<'\n';
}
return 0;
}