末三位整数

来源:互联网 发布:怎样登录淘宝达人平台 编辑:程序博客网 时间:2024/06/02 22:58

    这是编程挑战-高校俱乐部的题目。求(3 + √5)^n的小数点前(整数部分)的最低3位。 例如:(3 + √5)^5 = 3935.73982…则输出935 而(3 + √5)^2 = 27.4164079.. 则输出027。 输入格式: 多组数据,每组一行包含一个正整数n, 2<=n<=2000000000。 输出格式: 每组数据输出一行,恰好包含3个数字。 

    看到这个题,感觉就是完全不是考验编程能力,而是更多考验数学能力。很明显,要是一个没有学过高等数学的人,基本不太可能解决这个问题(当然了,学了也解决不了的人也存在)。看这个题,输入变量n的变化范围很大,显然,这个题是有简便的解法的。

    笨办法是把这个数求出来,不过显然有难度。先不说这个复杂度,就是n大到一定程度的时候,计算机就不好表示这个数了,而且由于误差的存在,结果很有可能是错的。所以要换个思路。

    我看到这个题,想到的是菲波那契数列。为什么呢?因为如果a0=a1=1,那么n>1,an=((1+√5)/2)^n+(1-√5)/2)^n。an其实是个整数,但是却可以用两个无理数来表示。那这里是不是也有用呢。刚好,3 -√5是个小于1的小数,若有an=(3+√5)^n+(3-√5)^n这样类似的有理数序列,那不就很好算了,而且没有误差。很容易可以看出an是个整数,而且a0=2,a1=6。那现在问题就是,怎么来快速的求an?再参考菲波那契数列,通式怎么表达的。a[n]=a[n-1]+a[n-2]。那这里也可以用类似的表达式,a[n]=p*a[n-1]+q*a[n-2]。对于这样的数列,有通式a[n]=t*x1^n+s*x2^n。其中x1,x2是方程x^2=p*x+q的两个根。对应上已有的通式,可得到t=s=1, x1=3+√5, x2=3-√5,那么p=6,q=-4,即a[n]=6*a[n-1]-4*a[n-2]。由此公式可以从a0,a1开始很方便的得到任意an的值。

    既然an求出来了,那么我们需要的就是,(3+√5)^n=an-(3-√5)^n。可以看出,等式的第二项是个小于1的小数。故而左边的整数部分的末3位就等于an-1的末3位。取bn=an%1000,再迭代求解,可以得到an的末3为整数值。

    当然了,如果是一个个的迭代求解,事件复杂度就是O(N)了,这是绝对无法忍受的。很容易看出来,bn会是个循环的周期序列,经过验证,循环从b3开始,周期是100,这个循环部分的数字如下所示:

144 752 936 608 904 992 336 048 944 472 056 448 464 992 096 608 264 152 856 528 744 352 136 408 904 792 136 648 344 472 456 848 264 192 096 808 464 552 456 528 344 952 336 208 904 592 936 248 744 472 856 248 064 392 096 008 664 952 056 528 944 552 536 008 904 392 736 848 144 472 256 648 864 592 096 208 864 352 656 528 544 152 736 808 904 192 536 448 544 472 656 048 664 792 096 408 064 752 256 528

    从最后一个数开始,就会又从144开始不断循环。由此可以得到n>3时bn的值。

    至此,这个问题已经解决了,具体代码如下所示:

<pre name="code" class="cpp">#define LIMIT 1000#define TS 100//cycle is 100/* *consider a[n]=(3+√5)^n+(3-√5)^n *then, a[n]=6*a[n-1]-4*a[n-2], a[0]=2, a[1]=6 *(3-√5)^n is an decimal <1, so (3+√5)^n=a[n]-(3-√5)^n *the z number of it is a[n]-1 *According to a test, a[n]%1000 is a cycle of 100 from a[3]=144 *so n>=3, a[n]%1000=a[(n-3)%100]%1000*///2<=n<=2,000,000,000int last3Num(int n){    int a, b, c;    if(n==2)        return 27;    a=6;    b=28;    n=(n-3)%TS;    for(; n>=0; n--){        c=6*b-4*a+4*LIMIT;        c%=LIMIT;        a=b;        b=c;    }    return (LIMIT+b-1)%LIMIT;}





0 0
原创粉丝点击