题目:lbw很喜欢吃羊肉泡馍,有一天他做关于斐波那契数列的问题时候突然想为何不定义一种羊肉泡馍数呢?斐波那契数列大家
都知道就是f[n]=f[n-1]+f[n-2],f[1]=f[2]=1,那么现在定义羊肉泡馍数,首先每个羊肉泡馍数都要是斐波那契数,
其次每个羊肉泡馍数要与小于该数的所有斐波那契数都互质,第一个羊肉泡馍数是2,第二个是3,第三个是5,第四个是13。
那么,第n个羊肉泡馍数是多少呢?
Input
一个数n(0<n<=22000),表示第n个羊肉泡馍数。
Output
输出第n个羊肉泡馍数的前九位,如果这个数不超过九位,输出该数。
1.首先用到一个斐波那契素数原理:
哪些的Fibonacci数才是Fibonacci质数呢?这里先给出结论:
1. F(3)和F(4)是Fibonacci质数;从F(5)开始,某项为Fibonacci质数当且仅当它的项数为质数
2. 第k小的Fibonacci质数是以质数数列中的第k个数为项数的Fibonacci数( 除F(3)和F(4)之外 )
1. F(3)和F(4)是Fibonacci质数;从F(5)开始,某项为Fibonacci质数当且仅当它的项数为质数
2. 第k小的Fibonacci质数是以质数数列中的第k个数为项数的Fibonacci数( 除F(3)和F(4)之外 )
2.有了上面的定理就好办了;不过要注意会超过范围 这里用long double 可以保存很大很大的数据 同时又能保证前几位的精度;
因此我们就要知道第22000个素数大概在什么范围。10^6之内可以产生7万多个素数,因此我们可以先把10^6内的素数筛出来存到数组里,以便后面使用。
这个可以作为一个常识吧;
3.另外求第n个斐波那契数可以用递推打表法,也可以用一个原理,如下;
http://blog.sina.com.cn/s/blog_6ea2c6a20100x359.html
4.对于大数,有三种处理方法:int数组,char数组,和双精度 如longlong 甚至long double;
5.这份代码学了一个技巧就是怎么保留前面9位
1 int flag=0; 2 for(int i=5; i<=N; i++) //从第5项开始构建fib 3 { 4 if(flag) //说明前一项曾经降位 5 { fib[i]=fib[i-1]+fib[i-2]/10; flag=0; } 6 //为了对应计算当前项,前二项要降位再相加 7 //先默认当前fib不超过9为,将flag恢复为0, 8 else 9 fib[i]=fib[i-1]+fib[i-2]; 10 11 if(fib[i]>E) //已经超过9位,当前的fib要降一位 12 { fib[i]/=10; flag=1; } 13 }
6.最后给出代码
1 #include <stdio.h> 2 #include <string.h> 3 #include <math.h> 4 bool isprime[250010]; 5 int prime[25010]; 6 long double fib[250010]; 7 int main() 8 { 9 memset(isprime,0,sizeof(isprime)); 10 for(int i=2; i<=500; i++) 11 { 12 for(int j=i*i; j<=250000; j+=i) 13 isprime[j]=1; 14 } 15 int p=1; 16 for(int i=2; i<=250000; i++) 17 { 18 if(!isprime[i]) 19 { 20 prime[p++]=i; 21 } 22 } 23 prime[1]=3; 24 prime[2]=4; 25 memset(fib,0,sizeof(fib)); 26 fib[0]=fib[1]=1; 27 int flag=0; 28 for(int i=2; i<=250000; i++) 29 { 30 if(flag==1){fib[i]=fib[i-1]+fib[i-2]/10;flag=0;} 31 else {fib[i]=fib[i-1]+fib[i-2];flag=0;} 32 if(fib[i]>1e9){fib[i]/=10;flag=1;} 33 } 34 int n; 35 while(scanf("%d",&n)==1) 36 { 37 printf("%d\n",(int)fib[prime[n]-1]); 38 } 39 return 0; 40 }