简单直接的,假如一个<x,y>之间能约分说明被挡住了。
需要知道:1、2、。。。。n之间能被m整除的个数位n/m.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <vector>
using namespace std;
#define MAX_SIZE 110000
#define ll_int long long int
bool notPrime[MAX_SIZE];
int f[MAX_SIZE];//记录质因数个数
vector<int> prime;
int find_min(int x,int y)
{
return x>y?y:x;
}
void init()
{
//先筛法求素数
memset(notPrime,0,sizeof(notPrime));
memset(f,0,sizeof(f));
int pre=0;
for(int i=4;i<MAX_SIZE;i+=2)
{
notPrime[i]=1;
}
//把所有的素数放入一个数组中
prime.push_back(2);
for(int j=3;j<MAX_SIZE;j+=2)
{
if(!notPrime[j])
{
prime.push_back(j);
f[j]=1;
for(int k=j+j;k<MAX_SIZE;k+=j)
notPrime[k]=1;
}
}
//计算每个数有多少个质因数
f[1]=0;
for(int k=2;k<MAX_SIZE;++k)
{
if(notPrime[k])
{
int val=k;
for(int i=0;i<prime.size();i++)
{
if(val%prime[i]==0)
{
val/=prime[i];
++f[k];
}
if(val%prime[i]==0)
{
f[k]=-1;
}
if(val<prime[i]||f[k]==-1)
break;
}
}
else f[k]=1;
}
}
int main()
{
int k;
int m,n;
scanf("%d",&k);
init();
while(k--)
{
scanf("%d%d",&m,&n);
int count=find_min(m,n);
ll_int ans=0;
for(int i=1;i<=count;i++){
if(f[i]>=0)
{
ans+=f[i]&1?-((ll_int)m/i)*((ll_int)n/i):((ll_int)m/i)*((ll_int)n/i);
}
}
printf("%lld\n",ans);
}
return 0;
}