题目描述:
解析:
emmm,n 挺大的,所以暴力应该是不能够解决的,然后是序列求解,想到得找序列规律、重复
根据递推公式:
当 时,f(n) 取决于 f(n - 1) 和 f(n - 2) ,即,当序列中有两个数对(数对中两数相邻)相同时,由此数对开始至下一数对是一个循环节。
因为 ,则不同的数对最多有 49 对,故可以列举序列前 51 个数(共50对,必有重复数对),从中查找循环节。
- 注:不一定是数对(1, 1)有可能前面部分序列不在循环中,而从中间某一处再开始循环
代码:
#include<stdio.h>
int seq[55];
int main()
{
int a, b, n;
while(scanf("%d%d%d", &a, &b, &n) && (a != 0 || b != 0 || n != 0)) // 判断是否 a = b = n = 0
{
// 生成序列的前 51 个
seq[1] = seq[2] = 1;
for(int i = 3; i < 52; i++)
seq[i] = (a * seq[i - 1] + b * seq[i - 2]) % 7;
// 找循环节
int beg = 1; // 开始循环的位置
int cyc = 1; // 循环周期
bool flag = false; // 是否找到循环节
while(beg < 50 && !flag)
{
cyc = 1;
while(cyc + beg < 51 && !flag)
{
if (seq[beg] == seq[beg + cyc] && seq[beg + 1] == seq[beg + cyc + 1])
{
flag = true;
break;
}
cyc++;
}
beg++;
}
// 求 f(n)
int ret; // 返回值
if (n < beg + cyc) // n 在第一个周期内或不在周期
ret = seq[n];
else // n 不在第一个周期
{
int t = (beg - 1)+ (n - beg + 1) % cyc;
ret = seq[t == 0 ? cyc : t];
// 因为没有定义 seq[0]
// (beg = 1 && n % cyc == 0)即 t == 0 时与 t != 0 时得分开讨论
}
printf("%d\n", ret);
}
return 0;
}