递归及递推问题系列之 Number Sequence hdoj 1005

/*
Number Sequence

http://acm.hdu.edu.cn/showproblem.php?pid=1005
Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 102808    Accepted Submission(s): 24878


Problem Description
A number sequence is defined as follows:

f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7.

Given A, B, and n, you are to calculate the value of f(n).

 

Input
The input consists of multiple test cases. Each test case contains 3 integers A, B and n on a single line (1 <= A, B <= 1000, 1 <= n <= 100,000,000). Three zeros signal the end of input and this test case is not to be processed.

 

Output
For each test case, print the value of f(n) on a single line.

 

Sample Input
1 1 3
1 2 10
0 0 0
*/
/*
根据数论,取余的运算是有规律的,即为周期性,现在就是确定周期是多少,我看了好多的博客,有写49的,有写48的(正确因为49,48也对的原因是这个题巧了,a[1]=a[2]=1,所以是一样的),关于这个准确值我想了好久确定不下来,有一个简单容易理解的方法,就是多打表几次,算出多个周期的最小公倍数...很容易理解,它的评测数据是有问题的,没有考虑到a,b是7 的倍数的情况...若是7的倍数,则序列应为110000000000......

*/
/*
1、根据周期,可以快速获得结果,且周期必定小于49.
   周期的原因:如果<f(x),f(x+1)>的值与<f(x+T),f(x+1+T)>一致,那么以后的序列就完全一致了。
   周期小于49的原因: 由于mod 7,所以<f(x),f(x+1)>的可能为49个,那么50个这样的<f(x),f(x+1)>必定有两个相同(鸽笼原理),所以最终可以确定周期小于49.
2、需要注意的是:并不是整个序列是有周期的,而是其中去掉头部一部分以后是有周期的!!!举个特殊的例子A=7,B=7,那么{f(x)}为{1,1,0,0,0,0,...},其在去掉头部的两个1后是有周期的,所以应该求出这个头部。类似的例子还有{A=2,B=7},{A=3,B=7}...

*/
/*
由于此题只可能出现7个数(0,1,2,3,4,5,6),而当两个连续数出现过两次,则开始循环;
由7个数中的任意两个组成一组,一共有49种不同的组,这49种不同的组出现在同一个数串中并且不重复,则这一数串必定为50个数(后面解析为什么);
当有51个数时,则里面一定有相同的组,所以,最大周期为49。

解析:49种不同的组出现在同一个数串中并且不重复,则这一数串必定为50个数
举个例子吧。
假如只出现两个0和1,按2个数为一组,则共有00 01 10 11四个组;
当一个数串为00110时,4个组都出现在这个数串中,并且没有重复的组,数串共有5(4+1)个数。
你能够举出数串不为5个数,并且数串不重复地包含所有组吗?

如果你看到这里还不理解,则自己试着用只出现3个数(可以是0,1,2)的情况下,用上面的方法找出包含所有组并且不重复的数串,你可能就明白了。

最后再说一点,你仔细看一上,当找到这条包含所有组并且不重复的数串时,数串的第一个数和最后一个数是什么?
 

*/

本人AC代码:
#include<cstdio>
#include<string.h>
#include<stdlib.h>
#define M 100
int f[M];
int main()
{
 
  int A,B,n;
  while(scanf("%d%d%d",&A,&B,&n),(A||B||n))
  {
   memset(f,0,sizeof(f));
   f[0]=0;
   f[1]=f[2]=1;
   int i;
   for(i=3;i<=48;i++)
       f[i]=(((A%7)*(f[i-1]%7)%7)%7+(((B%7)*(f[i-2]%7))%7)%7)%7;
     printf("%d\n",f[n>48?n%48:n]%7);
  } 
return 0;
}
/*

他人代码:

#include<stdio.h>

int main()
{
 int i,n,A,B;
 int f[50],num;

 while(scanf("%d%d%d",&A,&B,&n)!=EOF && (A || B || n))
 {
  f[1] = 1;
  f[2] = 1;
  for(i=3; i<=49; i++)
  {
   f[i] = (A * f[i-1] + B * f[i-2]) % 7;
   if(f[i] == f[i-1] && f[i] == 1) //判断是否出现周期
    break;
  }
  num = i-2;
  n = n % num;
  if( n == 0)
   printf("%d\n",f[num]);
  else
   printf("%d\n",f[n]);
 }
 return 0;
}

*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值