Title:
solution:
对于点(x,y),如果gcd(x,y)=1,那么这个点就能被看到,
否则这个点一定会被(x/gcd(x,y),y/gcd(x,y))挡住.
那么问题变为计算n*m的矩阵中,有多少个点横纵坐标互质.
ans = ∑ i = 1 n ∑ j = 1 m [gcd (i, j) = 1] There is an inversion conclusion: [gcd (i, j) = 1] = ∑ d ∣ gcd (i, j) μ (d ) Then: ans = ∑ i = 1 n ∑ j = 1 m ∑ d ∣ gcd (i, j) μ (d) Change the enumeration order, first enumerate d, then: ∑ d = 1 n μ (d ) ∑ d ∣ i, i <= n ∑ d ∣ j, j <= m 1 ∑ i = 1 n μ (d) ⌊ nd ⌋ ⌊ md ⌋ It can be optimized to O (n) ans = \sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)=1]\\ There is an inversion conclusion: [gcd(i,j)=1]=\sum_{d |gcd(i,j))\mu(d)\\ Then there is: ans=\sum_{i=1}^n\sum_{j=1}^m\sum_{d|gcd(i,j)} \mu(d)\\ Change the enumeration order, first enumerate d, then: \\ \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\\ hitting a number theory block can be optimized to O(\sqrt n) a n s=i=1∑nj=1∑m[gcd(i,j)=1]Exist in the anti- play knot theory:[gcd(i,j)=1]=d∣gcd(i,j)∑μ ( d )That it has:a n s=i=1∑nj=1∑md∣gcd(i,j)∑μ ( d )More change pieces move forward order ,First gold cite d ,That it has:d=1∑nμ ( d )d∣i,i<=n∑d∣j,j<=m∑1i=1∑nμ ( d ) ⌊dn⌋⌊dm⌋Then play a number of on sub blocks may be to optimization of the 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;
}