问题说明
数字序列定义如下:
f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7.
给定A,B和n,你要计算f(n)的值。
输入
输入包含多个测试用例。每个测试用例在单行上包含3个整数A,B和n(1 <= A,B <= 1000,1 <= n <= 100,000,000)。三个零表示输入结束,并且不处理此测试用例。
输出
对于每个测试用例,在一行上打印f(n)的值。
示例输入
1 1 3
1 2 10
0 0 0
示例输出
2
5
代码
#include <iostream>
using namespace std;
int f[54] = {0, 1, 1};
int main()
{
int A, B, n, q = 1;
while (cin >> A >> B >> n && A && B && n)
{
for (int i = 3; i < 54; ++i)
{
f[i] = (A * f[i - 1] + B * f[i - 2]) % 7;
if (i > 4)
{
if (f[i - 1] == f[3] && f[i] == f[4]) //here too
{
q = i - 4; //I can't catch the point
}
}
}
cout << f[n % q] << endl;
}
return 0;
}
答案 0 :(得分:11)
鉴于f(n)
完全由f(n - 1)
和f(n - 2)
确定,且f(x)
是0到6之间的整数,因此只有7 * 7 = 49种组合f(n - 1)
和f(n - 2)
。这意味着f(x)
是定期的,最长期限为49.一旦我们知道了这段时间,计算f(n)
就像f(n % period)
一样简单,因为我们计算了f(0)..f(48)
。确切的期限取决于A
和B
,需要进行计算。为了计算周期,我们只需要找到两个连续值f
的重复。也就是说,如果f(x) == f(y) && f(x + 1) == f(y + 1)
,则|y - x|
是f
的句点或其整数倍。请注意,f(n) == f(n % (k*period))
的效果与f(n) == f(n % period)
相同。因此,在问题q
中,代码是f
的句号或其整数倍。
现在,为什么代码预先计算f(0)..f(53)
而不是f(0)..f(48)
?我认为这是一种矫枉过正,因为超出最长期限的两个额外元素就足够了。
有关代码的另一个令人不安的事情是,f[0]
是假值,如果n
是q
的倍数,则可能会返回该值。这可能是一个错误。为防止这种情况发生,我会将f
的索引编制为一,将f(0) == 1 && f(1) == 1
而不是f(1) == 1 && f(2) == 1
。{/ p>
答案 1 :(得分:8)
是的,这种问题应该是OnlineJudge(OJ)的一个问题。也许你是ACM的新手?
Blew是我的答案:
解决方案可以解决的原因是因为mod 7
,这意味着答案只能是0,1,2,3,4,5,6。所以,这个问题只能从3到54循环,因为足够了。怎么说,因为f [n]只用f [n-1]和f [n-2]之前的两个值确定,f [n-1]有7个选择(0-6)所以f [的n-2]。
所以具有更多49的循环就足够了,当一些f [n-1]和f [n-2]等于f [4]和f [3]时,以下值将循环。
看看你的第二个例子。
f[1] = 1
f[2] = 1
A = 1
B = 2
n = 10 // or set n larger.
我们会得到
f[3] = 3
f[4] = 5
f[5] = 4
f[6] = 0
f[7] = 1
f[8] = 1
f[9] = 3
f[10] = 5
f[11] = 4
作为f[9] == f[3]
和f[10] == f[4]
,然后它将在数字4, 0, 1, 1, 3, 5
,
所以q = i - 4
删除了前四个数字,因为n%q
是循环序列中第n个数字的位置。
我想知道我是否清楚地说明了答案,希望这对你有所帮助。