标签:
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