pku3090 pku2478(欧拉函数的应用,法雷级数)
2010-07-17 18:07
274 查看
http://162.105.81.212/JudgeOnline/problem?id=3090
题目大意:一个(n+1)*(n+1)的点阵,问多少点能被点(0,0)看到。如果(0,0)到(i,j)的连线被点挡住就算看不到。
先画一条(0, 0)到(n, n)的线,把图分成两部分,两部分是对称的,只需算一部分就好。 取右下半,这一半里的点(x, y)满足x >= y 可以通过欧拉函数计算第k列有多少点能够连到(0, 0) 若x与k的最大公约数d > 1,则(0, 0)与(x, k)点的脸先必定会通过(x/d, k/d),就被挡住了 所以能连的线的数目就是比k小的、和k互质的数的个数,然后就是欧拉函数。由于是对称的,所以只需算一半的数量就够了。
第k列上的一个点的纵坐标为d,若gcd(k,d) != 1,则远带你与该点的连线必须通过(k/gcd,d/gcd),肯定被挡住了。
由此我们可以得到递推公式 res1[i] = res1[i-1] + 2*phi[i];其中phi[i]是第i列上能看到的点的个数,
这是欧拉函数的解法:
#include<iostream> using namespace std; const int maxn = 1005; int phi[1005]; __int64 a[1005]; void euler() { int i,j; for(i=1; i<=maxn; i++) phi[i] = i; for(i=2; i<=maxn; i+=2) phi[i] /= 2; for(i=3; i<=maxn; i+=2) if(phi[i] == i) { for(j=i; j<=maxn; j+=i) phi[j] = phi[j] / i * (i - 1); } } int main() { int t,n,i,j; euler(); a[1] = 3; for(i=2; i<=1000; i++) a[i] = a[i-1] + phi[i]*2; scanf("%d",&t); for(i=1; i<=t; i++) { scanf("%d",&n); printf("%d %d %I64d/n",i,n,a ); } return 0; }
还有其他解法:
递推:数组ans[i,j]表示一个0..i*0..j的点阵能被看到的点数。容易发现一个点(i,j)只有gcd(i,j)=1时才能被看到,否则必被(i/gcd(i,j),j/gcd(i,j))挡住!因此容易想到递推方程ans[i,j]=ans[i-1,j]+ans[i,j-1]+ans[i-1,j-1],if gcd(i,j)=1 then ans[i,j]++。
直接求解:一个点(x,y)没有被之前的点挡住等价于x和y的最大公约数为1
因为测试数据组数很多,所以做成O(N^2)的预处理和O(1)的询问
另外还可以利用图形的对称性。
void Init() { N = 1000; Count[0] = 0; for(int i = 1; i <= N; ++i) { Count[i] = Count[i-1]; for(int j = 0; j <= i; ++j) if(GCD(i,j)==1)++Count[i]; } for(int i = 1; i <= N; ++i) Count[i] = Count[i]*2-1; }
R.亨斯贝尔格著李忠翻译的《数学中的智巧》一书,介绍了法雷级数。这里每一行从0/1开始,以1/1结尾,其它数自左至右将所有的真分数按增加顺序排列;第n行是由所有分母小于或等于n的真分数组成,我们称为n阶法雷级数。如下表:
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
法雷级数Fn具有很多美妙的性质,下面是一些常见的性质:
1.如果a/b,c/d是相邻的两项,则abs(a*d-b*c)=1。
2.如果a/b,c/d,e/f是相邻的三项,则 (a+e)/(b+f)=c/d,特别的,如果c/d是新添加的,即c/d不属于F(n-1),则c=a+e;d=b+f。
性质2对于这个问题至关重要,它的证明可以参见哈代(Hardy)写的数论导引第三章
关于Farey级数的介绍。根据这条性质可以知道,丛F(n−1)到F(n)的构造过程中,F(n)的新项的分母一定是其相领两项的分母和。另一方面,如果F(n−1)中的相邻两项 a/b,c/d, b+d=n,则(a+c)/n一定会被添加到F(n)中。
相关文章推荐
- poj 2478/3090 欧拉函数应用(Farey 序列/斜率判重)
- poj 3090 && poj 2478(法雷级数,欧拉函数)
- poj 3090 && poj 2478(法雷级数,欧拉函数)
- (Relax 数论1.9)POJ 3090 Visible Lattice Points(欧拉函数的应用:计算前n项欧拉数之和)
- poj 3478 poj 3090(欧拉函数的应用)
- POJ 2478 Farey Sequence(法雷级数+欧拉函数递推)
- POJ 2478 Farey Sequence & POJ 3090 Visible Lattice Points (欧拉函数)
- [数学-欧拉函数]Pku2478--Farey Sequence
- 欧拉函数:poj 2407, poj 1284,poj 2478,poj 3090,poj 3696,poj 3358
- pku 2478 Farey Sequence 欧拉函数~~~
- poj 3090 欧拉函数简单应用
- hdu 2478||3090 欧拉函数
- POJ1284 2773 2478 3090 3358 简单欧拉函数5题
- uva 10820 poj 2407 poj 1284 poj 2478 poj 3090 (欧拉函数入门)
- POJ 3090 Visible Lattice Points 欧拉函数的应用
- pku2480(欧拉函数的应用,推公式,积性函数)
- (Relax 数论1.8)POJ 2478 Farey Sequence(欧拉函数:前n项欧拉数之和)
- 欧拉函数の应用;;;
- hdu2588gcd-欧拉函数应用
- POJ2480 Longge's problem 欧拉函数的应用 && 积性函数