Yuan Ye's gcd
First, be sure that this is the number one topic
Therefore, topic is: \ (\ sum_. 1} = {I ^ N \ sum_. 1} = {J ^ M [GCD (I, J) \ in Prime] \)
Then you can push a pleasant expression of ~
First, you can follow the routine enumeration prime and gcd
\(\sum_{p \in prime}\sum_{i=1}^N\sum_{j=1}^M[gcd(i,j)=p]\)
So we can obviously \ (I \) and \ (J \) simultaneously divided by \ (P \) , to give
\ (\ sum_ {p \ in prime} \ sum_ {i = 1} ^ {N} \ sum_ { j = 1} ^ {M} [gcd (\ frac ip, \ frac jp) = 1] \)
That is equivalent to
\ (\ sum_ {p \ in prime} \ sum_ {i = 1} ^ {\ frac Np} \ sum_ {j = 1} ^ {\ frac Mp} [gcd (i, j) = 1] \)
To here, we found that for \ ([gcd (i, j ) = 1] \) we can define the function Möbius \ (\ sum_ {d \ mid n} \ mu (d) \ = [n = 1] \) to be replaced, i.e.,
\(\sum_{p \in prime}\sum_{i=1}^{\frac Np}\sum_{j=1}^{\frac Mp}\sum_{d\mid i,d\mid j} \mu(d)\)
We can follow the routine \ (d \) in advance (here we default \ (N \ Le M \) )
\(\sum_{p \in prime}\sum_{d=1}^{\frac Np}\mu(d)\sum_{i=1}^{\frac Np}[d\mid i]\sum_{j=1}^{\frac Mp}[d\mid j]\)
Then we can find behind those two \ (\ sum \) can be divisible block out, that is,
\(\sum_{p \in prime}\sum_{d=1}^{\frac Np}\mu(d)\lfloor\frac N{dp}\rfloor\lfloor\frac M{dp}\rfloor\)
In this case, we use a little trick, the last formula \ (dp \) into \ (Q \)(Also known as Liu Chen Xue Ke Cui Jia He):
\(\sum_{Q=1}^N \sum_{p \in prime}\mu(\frac Qp)\lfloor\frac N{Q}\rfloor\lfloor\frac M{Q}\rfloor\)
For \ (\ sum_ {P \} in Prime \ MU (\ Qp of FRAC) \ lfloor \ N FRAC {Q} \ rfloor \ lfloor \ FRAC {Q M} \ rfloor \) , we may be pretreated with a linear screen, that is screening out \ (\ varphi \) enumeration after. Therefore, maintenance and after you can prefix for each inquiry \ (O (1) \) answered friends ~
\(\mathcal{Code:}\)
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
#define N 10000010
#define debug cout<<__LINE__<<" "<<__FUNCTION__<<"\n"
inline int read(){
int x=0;char ch=getchar();
while(ch<'0'||ch>'9'){ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x;
}
void put(long long x){
if(x<0) putchar('-'),x=-x;
if(x>=10) put(x/10);
putchar((x%10)+48);
}
int prime[N>>2],n,m,cnt;
bool ispri[N];
int mu[N],num[N];
inline void pri(){
register int i,j;
for(i=2;i<=N-10;i++){
if(!ispri[i]){
prime[++cnt]=i;
mu[i]=-1;
}
for(j=1;j<=cnt&&(i*prime[j]<=N-10);j++){
if(i*prime[j]<=N-10) ispri[i*prime[j]]=1;
if(i%prime[j]==0){
break;
}else{
mu[i*prime[j]]=-mu[i];
}
}
}
int res;
for(i=1;i<=cnt;i++){
res=1;
for(j=prime[i];j<=N-10;j+=prime[i],res++){
num[j]+=mu[res];
}
}
for(i=2;i<=N-10;i++) num[i]+=num[i-1];
}
signed main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
mu[1]=1;
pri();
int T=read(),l,r;
long long ans = 0;
while(T--){
n=read();m=read();ans=0;
if(n>m) swap(n,m);
for(l=1,r;l<=n;l=r+1){
r=min(n/(n/l),m/(m/l));
ans+=(long long)(num[r]-num[l-1])*(n/l)*(m/l);
}
put(ans);putchar('\n');
}
// fclose(stdin);
// fclose(stdout);
return 0;
}