题意是农夫站在(0,0) 在(1,1)-(m,n)的矩形的每个点上种满树。
前面的数会挡住后面的树。
农夫能看见多少树。
这题就是连接农夫与任意一棵树,有多少种不同的斜率即能看到多少树,但是直接暴力做肯定超时。
如果(x,y)互质,即是新树,否则已经有过这棵树。
那么x从1-m 对于每一个x 寻找y在1-n之间又多少个与x互质的数。
这里用到容斥定理,寻找不互质的,总数相减。
例如2 2
1 2与1互质 斜率有1/1 2/1
1 与2互质 斜率有1/2
总数为3
#include<stdio.h>
#include<string.h>
int pr[444],num,id[444],a[1111];
__int64 x,y;
__int64 ans;
int cnt;
void get_s()
{
memset(id,0,sizeof(id));
int i;
num=0;
int j;
for(i=2;i<444;i++)
{
if(id[i]==0)
{
num++;
pr[num]=i;
}
for(j=1;j<=num&&pr[j]*i<444;j++)
{
id[pr[j]*i]=1;
if(i%pr[j]==0) break;
}
}
}
void dfs(int id,__int64 lcm,int num,__int64 x)
{
lcm=lcm*a[id]; //lcm是最小公倍数,因为是不同的质因数,直接相乘。
if(num&1)
ans+=x/lcm;
else
ans-=x/lcm;
for(int i=id+1;i<=cnt;i++)
dfs(i,lcm,num+1,x);
}
int main()
{
__int64 d,putt;
get_s();
int i,zz=1,j,k;
int T,m;
scanf("%d",&T);
while(T--)
{
scanf("%I64d%I64d",&x,&y);
if(x>y)
{
d=x;
x=y;
y=d;
}
putt=y;
for(i=2;i<=x;i++)
{
d=i;
cnt=0;
ans=0;
for(j=1;j<=num;j++) //获得质因数
{
if(d==1) break;
if(d%pr[j]==0)
{
cnt++;
a[cnt]=pr[j];
while(d%pr[j]==0)
d/=pr[j];
}
}
if(d!=1)
{
cnt++;
a[cnt]=d;
}
for(k=1;k<=cnt;k++)
dfs(k,1,1,y);
ans=y-ans; //把ans从不互质的变成互质的
putt+=ans;
}
printf("%I64d\n",putt);
}
return 0;
}