题意:有一个n*m的矩阵上布满了树(矩阵从(1,1)开始),现在有一个农夫站在(0,0)点,问农夫可以看到多少棵树,其中如果这些树在一条线上那么只能看到最前面的那棵树,这个一开始看到确实蒙了。。看了题解其实是挺简单的。首先考虑只能看到一条线上最前面的那棵树这个条件,对于坐标 比如 (2,3)(4,6)(6,9)。。等 这些坐标是在一条直线上的 可以看出其除了(2,3) 其他的都是由(2,3)的x坐标*k y坐标*k 得到的, 拓展出来就是对于 任意坐标 (x,y) 令a=x/gcd(x,y) b=y/gcd(x,y) 那么那些和(x,y) 在一条直线的点的坐标可以表示为 (x+(-)a*k,y+(-)b*k) ,显然(a,b) 是这条线上的第一个点,即农夫可以看到的点,所以总的问题就可以转换为求x∈(1,n)y∈(1,m)范围内满足 x,y互质的坐标的个数。枚举(1,n)内的x坐标 ,求x与(1,m)内互质的数个数。
2 1 1 2 3
1 5
#include<stdio.h>
#include<iostream>
using namespace std;
int s[100020],k;
void init(int m)
{
k=0;
for(int i=2;i*i<=m;i++)
{
if(m%i==0)
{s[k++]=i;
while(m%i==0)
m/=i;
}
}
if(m>1)
s[k++]=m;
}
int quc(int m)
{
int t=0,p[100020],z;
long long sum=0;
p[t++]=-1;
for(int i=0;i<k;i++)
{
z=t;
for(int j=0;j<z;j++)
{
p[t++]=p[j]*s[i]*(-1);
}
}
for(int i=1;i<t;i++)
{
sum+=m/p[i];
}
return sum;
}
int main()
{
int n,a,b;
long long sum;
scanf("%d",&n);
while(n--)
{sum=0;
scanf("%d %d",&a,&b);
for(int i=1;i<=a;i++)
{init(i);
sum+=b-quc(b)+quc(0);
}
printf("%I64d\n",sum);
}
}
hdu 2841 树围成矩阵,人在(0,0)点,最多可看到几棵树
原文:http://blog.csdn.net/maqinyao5566/article/details/51334628