从0,0的点向矩阵中看,如果点(x,y)&&gcd(x,y)=1那么,他是可以被看到的否则,不能被看到
结论:两个数字(x,y)如果两数互质,则可以被看到,如果不互质,则看不到,所以我们就是要找出所有的二元组(x,y)使他们互质
这题,可以枚举x,求1~y中有多少数与x互质,互质不好求,可以求不互质的数的个数,x与1~y中不互质的数的数对个数,就是1~y中以x的质因数为倍数的数
因为最小分解就只能是质数,且这些质数可以包含所有情况,所以对1~y中以x的质因数为倍数的数,进行容斥求出答案即可
#include<cstdio>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
const int N=100009;
ll sum[100009],p[100009],pri[100009],id=0;
bool b[N];
void getp()
{
p[1]=1;
for (int i=2;i<N;i++)//线性筛最小质因子
{
if (!b[i])
{
p[i]=i;
pri[++id]=i;
}
for (int j=1;j<=id&&i*pri[j]<N;j++)
{
b[i*pri[j]]=true;
p[i*pri[j]]=pri[j];//由于线性筛就是根据最小质因子的性质来筛的
if (i%pri[j]==0) break;//所以不妨利用一下来求最小质因子
}
}
//for (int i=99900;i<=100000;i++) printf("%d : %d\n",i,p[i]);
}
ll kk(ll x,ll y)
{
ll h[109];
ll ans=y,k,id;
memset(h,0,sizeof(h));
while (x>1)
{
h[++h[0]]=p[x];
while (x%h[h[0]]==0)x/=h[h[0]];
}
for (int i=1;i<(1<<h[0]);i++)
{
k=1;id=0;
for (int j=0;j<h[0];j++)if (i&(1<<j)) id++,k=k*h[j+1];
if (id&1) ans-=y/k;else ans+=y/k;
}
return ans;
}
ll work(ll n,ll m)
{
ll ans=0;
for (int i=1;i<=n;i++) ans+=kk(i,m);
return ans;
}
int main()
{
getp();
ll n,m,T;
scanf("%lld",&T);
while (T--)
{
scanf("%lld%lld",&n,&m);
printf("%lld\n",work(n,m));
}
return 0;
}