1. 程式人生 > >POJ3090:Visible Lattice Points——題解

POJ3090:Visible Lattice Points——題解

題解 lin 但是 函數 get span ace har type

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; }

POJ3090:Visible Lattice Points——題解