题目大意: 给斐波拉契数列的一项值Ak,问k值(1<=k<=100000)
因为斐波拉契后面的项都已经是大数范畴,所以我们很难记录实际值!
我们选择用5个质数取模,得到的5个余数,表示这项值! 暴力打表,
证实可以抗碰撞(没有两个项的余数数组一模一样)!
时间复杂度为O(T*5*n)!
常用hash质数:https://blog.csdn.net/shiyongyang/article/details/78079109
/********************************
*** 多重哈希
*** 将一项斐波拉契项与多个质数取模得出结果,保证每一项不同
********************************/
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define llt long long
using namespace std;
const int N = 1e5+7;
llt mod[6]={1000000007,1000000009,91815541,68861641,51646229};
llt F[N][6];
llt a[6];
char s[N];
int main(){
for(int i=1;i<=2;++i)
for(int j=0;j<5;++j)
F[i][j] = i;
for(int i=3;i<=1e5;++i)
for(int j=0;j<5;++j)
F[i][j] = (F[i-1][j]+F[i-2][j])%mod[j];
while(~scanf("%s",s)){
int len = strlen(s);
/*得到输入数的5个hash对应值*/
for(int i=0;i<5;++i) a[i] = 0;
for(int i=0;i<len;++i){
int sn = s[i] - '0';
for(int j=0;j<5;++j)
a[j] = (a[j]*10+sn)%mod[j];
}
//查询
int i;
int flag=0;
for(i=1;i<=1e5&&!flag;++i){
flag = 1;
for(int j=0;flag&&j<5;++j)
if(F[i][j]!=a[j])flag=0;
}
cout<<i-1<<endl;
}
return 0;
}