POJ-3090 Visible Lattice Points

来源:互联网 发布:逛1小时淘宝用多少流量 编辑:程序博客网 时间:2024/04/29 13:56

题目:

http://poj.org/problem?id=3090

题意:

就是给出一个二维点阵的大小,问从(0,0)点能看到的点的个数。

思路:

一开始最基本的思路就是枚举斜率,所有斜率相同的点是重复的,数据小就1e3,所以理论上那个可行。

之后发现所有能看到的点的斜率也就是分子分母互质的数,也就是所有真分数的个数。

后来知道这叫做法雷级数,像这样:

      F1: 0/1 1/1

  F2: 0/1 1/2 1/1

  F3: 0/1 1/3 1/2 2/3 1/1

  F4: 0/1 1/4 1/3 1/2 2/3 3/4 1/1

  F5: 0/1 1/5 1/4 1/3 2/5 1/2 3/5 2/3 3/4 4/5 1/1

  F6:0/1 1/6 1/5 1/4 1/3 2/5 1/2 3/5 2/3 3/4 4/5 5/6 1/1

然后就是法雷级数的求法。可以转换成求小于等于n的所有数i的小于等于i的与i互质的数的个数,比较绕口,简单地说就是求所有小于等于n的数的欧拉函数之和。

到这里就没问题了,直接套欧拉函数就行了。注意这样求出来的是斜率小于1的,还有对称的另一半,另外法雷级数还包括1/0,数论还是等练练,看能不能想到。

代码:

#define N 11234long long  n,m;long long eul[N],num[N];void init(){     eul[1]=1;     for(long long i=2;i<N;i++)       eul[i]=i;     for(long long i=2;i<N;i++)        if(eul[i]==i)           for(long long j=i;j<N;j+=i)              eul[j]=eul[j]/i*(i-1);    num[0]=0;    for(int i=1;i<N;i++)        num[i]=num[i-1]+eul[i];}int main(){    int i,j,k,kk,t,x,y,z;    init();    scanf("%d",&k);    kk=0;    while(k--)    {        scanf("%lld",&n);        printf("%d %lld %lld\n",++kk,n,num[n]*2+1);    }    return 0;}








0 0
原创粉丝点击