菲波那契数的余数
Time Limit:1000MS Memory Limit:32768K
Description:
Input:
输入数据为一些整数对P、K,P(1<P<5000)表示菲波那契数的序号,K(1<=K<15)表示2的幂次方。遇到两个空格隔开的0时表示结束处理。
Output:
输出其第P个菲波那契数除以2的K次方的余数。
Sample Input:
6 2
20 10
0 0
Sample Output:
1
85
刚看到题,首先被题上面的斐波那契数吸引了,简单分析了一下题目。斐波那契数大家很熟,直接用一个for循环把所有的数列出来。由于题目要求是1<P<5000,所以把所有的数都装在一个大小为5000的数组里:
int a[5000];
a[1]=0;
a[2]=1;
for(int i=3;i<50;i++)
a[i]=a[i-1]+a[i-2];
然后根据题目写的条件,是将第P个斐波那契数除以2的K次方,取其余数,所以先将2的K次方算出来:
int m;
cin>>m;
int temp=2;
while(--m)
temp*=2;
最后直接用第n个来读取数组,然后除以temp,得出结果,代码如下:
#include<iostream>
using namespace std;
int main()
{
int a[5000];
a[1]=0;
a[2]=1;
for(int i=3;i<5000;i++)
{
a[i]=a[i-1]+a[i-2];
}
int n,m;
while(cin>>n>>m)
{
cout << a[n]<<endl;
int temp=2;
while(--m)
{
temp*=2
}
cout << a[n]%temp<<endl;
return 0;
}
结果提交的时候出现的是WA,原因是5000个超过int型的上限了,没办法把5000个全部算出来的。所以,只能再改变思路。
班里的数学天才告诉我:先理解什么叫余数。
a与b的和除以c的余数(a、b两数除以c在没有余数的情况下除外),等于a,b分别除以c的余数之和(或这个和除以c的余数)。例如,23,16除以5的余数分别是3和1,所以(23+16)除以5的余数等于3+1=4。注意:当余数之和大于除数时,所求余数等于余数之和再除以c的余数。例如,23,19除以5的余数分别是3和4,所以(23+19)除以5的余数等于(3+4)除以5的余数。
也就是说:
f1=f(1)=0;
f2=f(2)=1;
f(n)=f(n-1)+f(n-2);
f为余数,a[k]为2的K次方,
则f=f(n)%a[k]=(f(n-1)+f(n-2))%a[k]=(f(n-1)%a[k]+f(n-2)%a[k])%a[k];
下标: 1 2 3 4 5 6 7 8 9 ......
数值: 0 1 1 2 3 5 8 13 21......
相对应的余数;f1 f2 f=(f1+f2)%a[k]
f2 f1 f=(f1+f2)%a[k]
f2 f1 f=(f1+f2)%a[k]
#include<iostream>
using namespace std;
int main()
{
int f1 = 0, f2 = 1,p,k,f,i,temp;//f1是第一项为0,f2是第二项为1,余数皆为本身
int a[15] = {1};
for(i = 1; i < 15; i++)
{
a[i] = 2 * a[i-1];//除数:2的i次方
}
while(cin>>p>>k,p,k)
{
if(p <= 2)
cout<<p-1<<endl;//前两项直接输出
else
{
f = (f1 + f2) % a[k];//第三项的余数
for(i = 3; i < p; i++)
{
f1 = f;//第一项不需再用到,用来存上一个出来的余数
f = (f1 + f2) % a[k]; //算下一个余数
f2 = f1;//上一个余数移过来
}
cout<<f<<endl;
f1 = 0;
f2 =1;
}
}
return 0;
}