POJ3090:Visible Lattice Points——题解

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

题目大意:你站在(0,0)的点上看向第一向限的点,点和点会互相阻挡,问最多看到多少点。

很容易想到,我们能看到的点,它的横纵坐标一定是互质的,那么怎么求呢?

首先我们要知道一个东西叫做法雷级数:

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,分子与n互质,所以加入了与n互质的数的个数。
是不是欧拉函数啊(叫做E)
所以Fn=Fn-1+En
但是我们知道我们要求的F可以分子分母相反,那么实际我们求的是Fn*2-1(-1因为1/1)
#include<cstdio>
#include<cctype>
#include<iostream>
using namespace std;
inline int read(){
    int X=0,w=0; char ch=0;
    while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
    while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
int f[1001],e[1001];
bool h[1001];
int p[1001],cnt=0;
void Euler(int n){
    e[1]=1;
    for(int i=2;i<=n;i++){
    if(!h[i]){
        cnt++;
        p[cnt]=i;
        e[i]=i-1;
    }
    for(int j=1;j<=cnt&&i*p[j]<=n;j++){
        h[i*p[j]]=1;
        if(i%p[j]==0){
        e[i*p[j]]=e[i]*p[j];
        break;
        }
        e[i*p[j]]=e[i]*(p[j]-1);
    }
    }
    return;
}
void Farley(int n){
    f[1]=2;
    for(int i=2;i<=n;i++){
    f[i]=f[i-1]+e[i];
    }
    return;
}
int main(){
    Euler(1000);
    Farley(1000);
    int c=read();
    for(int i=1;i<=c;i++){
    int n=read();
    printf("%d %d %d\n",i,n,f[n]*2-1);
    }
    return 0;
}

 

posted @ 2017-11-26 14:12  luyouqi233  阅读(507)  评论(0编辑  收藏  举报