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
首先对于这道题,网上也有很多答案,并且都通过了hdu的测试,我试过他们的代码,都能通过。虽然都能通过,但是代码却不一定正确。接下来看一下网上通过hdu测试的代码(按照他们的思想,我自己写的代码):
#include <iostream>
#include<string>
using namespace std;
int main()
{
int a[50];
int A,B,n;
cin>>A>>B>>n;
a[1]=1;
a[2]=1;
for(;A!=0||B!=0||n!=0;)
{
for(int i=3;i<=49;i++)
{
a[i]=(A*a[i-1]+B*a[i-2])%7;
}
a[0]=a[49]; //防止周期恰好是49,这样取模之后值为0
cout<<a[n%49]<<endl;
cin>>A>>B>>n; //进行下一轮取值
}
return 0;
}
我们来写一下测试数据代码(目的是输出f(1)到f(200)之间的值,便于寻找周期和比较结果值):
#include <iostream>
#include<string>
using namespace std;
int main()
{
int a[205];
int A,B,n;
cin>>A>>B>>n;
a[1]=1;
a[2]=1;
cout<<1<<" "<<1<<endl;
cout<<1<<" "<<2<<endl;
for(int i=3;i<=200;i++)
{
a[i]=(A*a[i-1]+B*a[i-2])%7;
cout<<a[i]<<" "<<i<<endl;
}
return 0;
}
以A=1,B=1,为例,结果如下(第一列代表f(n),第二列值代表n):
仅选取了部分结果。我们看到当n=52时,f(52)=3;
那么用上述通过hdu测试的代码算出的结果是:
为什么结果不一致?因为按照上述算法,n=52,要对49取模,结果是3,f(52)=f(3)=2;
这时候就会出现,对于n>49,f(n)的值变成了f(n-1),结果都向后推移了一位。
原本 | 结果 |
---|---|
f(49)=1 | f(49)=1 |
f(50)=1 | f(50)=1 |
f(51)=2 | f(51)=1 |
f(52)=3 | f(52)=2 |
f(53)=5 | f(53)=3 |
这是对49取模的结果,虽然我不太明白,为什么要mod49,但49并不是其周期,故出现了连续三个1的结果,这样的结果居然还通过了测试!如果有理解的望大神指点。
接下来贴出我认为正确的代码(同样通过了hdu测试):
/*
具体思想:先求其周期,然后用周期对n求模
因为之前在求周期时已经将前200个结果存于数组,故求模后可直接去数组中取值
有人可能不理解为么要用前100个数据求周期,如果周期比100大怎么办?
这个可能就要用到上面的49这个数字了:f(n)最多有7中可能,那么,f(n-1)+f(n-2)最多有7*7=49中可能,故周期一定会在49以内。
将数组放缩到50应该也是可以的。
*/
#include <iostream>
#include<string>
using namespace std;
int main()
{
int a[100];
int A,B,n,i;
cin>>A>>B>>n;
a[1]=1;
a[2]=1;
for(;A!=0||B!=0||n!=0;)
{
//测试一组数据,寻找周期
for(i=3;i<100;i++)
{
a[i]=(A*a[i-1]+B*a[i-2])%7;
if(a[i]==1&&a[i-1]==1) break;
}
i=i-2; //此时i是其真正周期
n=n%i; //n对周期取模
if(n==0) n=i; //对n取模会出现0的情况,a[0]不存在,故n赋值周期
cout<<a[n]<<endl;
cin>>A>>B>>n; //输入下一组数据
}
return 0;
}