Wannafly挑战赛9 C、列一列 (多重hash查询)

题目链接

题目大意: 给斐波拉契数列的一项值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;

}

猜你喜欢

转载自blog.csdn.net/qq_38786088/article/details/81257931