题意:
解法:
对于点(x,y),如果gcd(x,y)=1,那么这个点就能被看到,
否则这个点一定会被(x/gcd(x,y),y/gcd(x,y))挡住.
那么问题变为计算n*m的矩阵中,有多少个点横纵坐标互质.
a n s = ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = 1 ] 存 在 反 演 结 论 : [ g c d ( i , j ) = 1 ] = ∑ d ∣ g c d ( i , j ) μ ( d ) 那 么 有 : a n s = ∑ i = 1 n ∑ j = 1 m ∑ d ∣ g c d ( i , j ) μ ( d ) 更 改 枚 举 顺 序 , 先 枚 举 d , 那 么 有 : ∑ d = 1 n μ ( d ) ∑ d ∣ i , i < = n ∑ d ∣ j , j < = m 1 ∑ i = 1 n μ ( d ) ⌊ n d ⌋ ⌊ m d ⌋ 再 打 个 数 论 分 块 可 以 优 化 到 O ( n ) ans=\sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)=1]\\ 存在反演结论:[gcd(i,j)=1]=\sum_{d|gcd(i,j)}\mu(d)\\ 那么有:ans=\sum_{i=1}^n\sum_{j=1}^m\sum_{d|gcd(i,j)}\mu(d)\\ 更改枚举顺序,先枚举d,那么有:\\ \sum_{d=1}^n\mu(d)\sum_{d|i,i<=n}\sum_{d|j,j<=m}1\\ \sum_{i=1}^n\mu(d)\lfloor\frac{n}{d}\rfloor \lfloor\frac{m}{d}\rfloor\\ 再打个数论分块可以优化到O(\sqrt n) ans=i=1∑nj=1∑m[gcd(i,j)=1]存在反演结论:[gcd(i,j)=1]=d∣gcd(i,j)∑μ(d)那么有:ans=i=1∑nj=1∑md∣gcd(i,j)∑μ(d)更改枚举顺序,先枚举d,那么有:d=1∑nμ(d)d∣i,i<=n∑d∣j,j<=m∑1i=1∑nμ(d)⌊dn⌋⌊dm⌋再打个数论分块可以优化到O(n)
code:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxm=1e5+5;
int p[maxm],c;
int np[maxm];
int mu[maxm];
int n,m;
void init(){
mu[1]=1;
for(int i=2;i<maxm;i++){
if(!np[i])p[c++]=i,mu[i]=-1;
for(int j=0;j<c;j++){
if(p[j]*i>=maxm)break;
np[p[j]*i]=1;
mu[p[j]*i]=i%p[j]?-mu[i]:0;
if(i%p[j]==0)break;
}
}
for(int i=1;i<maxm;i++){
mu[i]+=mu[i-1];
}
}
void solve(){
cin>>n>>m;
int mi=min(n,m);
int ans=0;
for(int l=1,r;l<=mi;l=r+1){
r=min(n/(n/l),m/(m/l));
ans+=(mu[r]-mu[l-1])*(n/l)*(m/l);
}
cout<<ans<<endl;
}
signed main(){
init();
int T;cin>>T;
while(T--){
solve();
}
return 0;
}