http://acm.hdu.edu.cn/showproblem.php?pid=1005
给出两个初值f(1) = 1;f(2) = 1 和 递推公式f(n) = (a * f(n - 1) + b * f(n - 2)) % 7
输入a,b,n 要求输出f(n)
1 <= n <= 100,000,000这个限制条件表示直接迭代n次注定是超时的结局
由迭代公式知道f(n)都由前两个数推导出来 而每个数都有7种可能 所以共有7*7=49种组合
所以根据鸽巢原理知 由该递推公式推导出50个连续的数,必有两对相同的数(形如1 1 2 3 4 5 6 1 1 2 3..中的1 1)
又因为a和b是常量,所以相同的两对数必会推出相同结果 这个效应传递下去就会导致循环周期的出现
所以该数列必有长度在49以内的循环周期
*但是周期不一定是从1 1开始的
*比如当a=605 b=903时 数列为1,1,3,2,6,4,5,1,3,2,6,4,5,1,3...可以看出周期为1,3,2,6,4,5 并不是从1 1 此处需注意
# include <stdio.h>
int f[55], a, b, n, Start, End;
bool Have_Circle(int pos)
{
for(int j = 1; j + 1 < pos; j++)
{
if(f[j] == f[pos - 1] && f[j + 1] == f[pos])//若出现一对相同的数 说明有周期
{
Start = j;//周期起点
End = pos - 2;//终点
return true;
}
}
return false;
}
int main()
{
while(scanf("%d %d %d",&a, &b, &n) && a && b && n)
{
f[1] = f[2] = 1;
for(int i = 3; i < 55; i++)
{
f[i] = (f[i - 1] * a + f[i - 2] * b) % 7;
if(Have_Circle(i))//查看是否出现周期
break;
}
//减去周期前的无用数字 模 周期长度
n = (n - (Start - 1)) % (End - Start + 1);
if(n)
printf("%d\n",f[n + (Start - 1)]);
else//若n == 0 则是周期最后一个数字
printf("%d\n",f[End]);
}
return 0;
}
原文:http://www.cnblogs.com/linjiaman/p/4296800.html