原题: http://acm.hdu.edu.cn/showproblem.php?pid=1005
题目:
Number Sequence
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 128931 Accepted Submission(s): 31368
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
Sample Output
2
5
思路:
类似于一个fib数列,但是每项都由前两项分别*a和*b之后再对7取余。
不难想到,f数列的每一项都只能为0到7的值。
那么每两项有7*7=49种情况。
所以第50项的前两项肯定在前面已经出现过了。
所以周期最多可能为49。
就像循环小数一样,后面的循环部分最多有49个字符长度,但是前面的部分不一定属于循环部分,所以我们这里从第100项开始求周期。
代码:
#include <iostream>
#include"stdio.h"
#include"math.h"
#include"string.h"
#include"algorithm"
using namespace std;
typedef long long int lint;
const int N =1000005;
int f[N];
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int a,b,n;
f[1]=1;
f[2]=1;
while(scanf("%d %d %d",&a,&b,&n)!=EOF)
{
int t=-1;
int st=0;
if(a==0&&b==0&&n==0) break;
//打到250的表,用来找规律,虽然用不到这么多
for(int i=3; i<=250; i++)
f[i]=((a%7)*(f[i-1]%7)+(b%7)*(f[i-2]%7))%7;
//枚举100到200内的所有可能的周期起点
for(int i=100; i<=200; i++)
{
for(int j=101; j<=200; j++)
{
//找到可能是周期起点的点
if(f[i]==f[j])
{
t=j-i;
//检查这一段是不是周期
for(int k=0; k<=t; k++)
{
if(f[k+i]!=f[k+j])
t=-1;
}
}
st=i;
if(t!=-1) break;
}
if(t!=-1) break;
}
if(n<=st) printf("%d\n",f[n]);
else printf("%d\n",f[(n-st)%t+st]);
}
return 0;
}