ACM--菲波那契数的余数

菲波那契数的余数
Time Limit:1000MS Memory Limit:32768K
Description:

菲波那契数大家可能都已经很熟悉了: f(1)=0 f(2)=1 f(n)=f(n-1)+f(n-2) n>2 因此,当需要其除以某个数的余数时,不妨加一些处理就可以得到。
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;
}







  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值