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.
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).
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 0Sample Output
2 5
刚开始这题看起来比较容易,因为直接用递归的话很容易搞定。但是提交的时候总是不AC,仔细一看有很多格式限制,比如内存,运行时间,堆栈大小等的限制。所以递归是行不通的。
在网上查看了一下相关思路,再看看n的范围可以那么大,用一般方法肯定不行,这时候就要想到其中的规律。我们仔细分析一下:
1。由题目的式子可知因为f[n]是%7后得出的结果,而%7后有7种结果0,1,2,3,4,5,6;
2。我们明白是f(n-1)有7种可能,f(n-2)有7种可能,而每个f[n]又是由(f[n-1],f[n-2])这个组合通过计算得出来的,由以上两点可以推出,(f[n-1],f[n-2])出现重复的组合的最大周期为7*7=49, 即f[n]的最大周期,所以超过49的数,结果一定在这里面。
弄清循环规律后,不管n有多大都可以通过取模将数字限制在6以内。
解决了数据范围问题,就可以使用记忆递归型动归来写了。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int F[50];
int A,B,n;
int f(int n)
{
if(F[n]!=-1) return F[n];
if(n==1||n==2) return 1;
else
{
F[n]=(A*f(n-1)+B*f(n-2))%7;
return F[n];
}
}
int main()
{
while(cin>>A>>B>>n&&A*B*n)
{
memset(F,-1,sizeof(F));
printf("%d\n",f(n%49));
}
return 0;
}