51nod 1126 求递推序列的第N项 思路:递推模拟,求循环节。详细注释

题目:

51nod 1126 求递推序列的第N项   思路:递推模拟,求循环节。详细注释

看起来比较难,范围10^9 O(n)都过不了,但是仅仅是看起来。(虽然我WA了7次 TLE了3次,被自己蠢哭)

我们观察到 0 <= f[i] <= 6 就简单了,就像小学初中学的找到循环节然后求第n项。

我们只用记录下两个连续的数字重复出现,就找到了循环节,然后就简单了。

注意:MOD函数是用于返回两数相除的余数,返回结果的符号与除数(divisor)的符号相同。(来自百度百科) ,mod结果正负所以要与7正负相同。

代码(详细注释):

#include <bits\stdc++.h>
using namespace std;
typedef long long ll; int f[]; // 存递推项。
int v[][]; // v[i][j]表示 f[k-1]和f[k]出现的位置,第二次出现就找到了循环节了。
int main() {
int a,b,n;
cin >> a >> b >> n;
int round ; // 循环节长度
f[] = f[] = ;
v[][] = ; // 1,1连续出现的位置是1
int start; // 循环节开始的位置-1。
for(int i = ;; i++){
f[i] = ((a*f[i-] + b*f[i-])%+)%; // 让f[i]变成成正数。
// cout << "i: " << i << " f: " << f[i] << endl;
if(i == n){
cout << f[i] << endl; // 如果求出循环节之前求出了答案,直接输出。
return ;
}
if(v[f[i-]][f[i]] == ){
v[f[i-]][f[i]] = i-; // f[i-1],f[i]第一次出现
}else{
// 第二次出现
round = i--v[f[i-]][f[i]]; // 循环节长度
start = v[f[i-]][f[i]]-; // 循环节开始的位置-1。
break;
}
}
n -= start; // 减去不在循环节之内的部分。
n = n % round; // 求出n在循环节中的位置。 //已知的循环节从 start+1 - start+round。
if(n == ) cout << f[start+round] << endl;
else cout << f[start+n] << endl;
return ;
}
//written by zhangjiuding.
上一篇:【bzoj4568 scoi2016】幸运数字


下一篇:短网址(short URL)系统的原理及其实现