牛客Wannafly挑战赛9C题-简单Hash哈希

链接:https://www.nowcoder.com/acm/contest/71/C
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

小W在计算一个数列 An A n ,其中 A1=1,A2=2,An+2=An+1+An A 1 = 1 , A 2 = 2 , A n + 2 = A n + 1 + A n 。尽管他计算非常精准,但很快他就弄混了自己的草稿纸,他找出了一些他计算的结果,但他忘记了这些都是数列中的第几项。

输入描述:

每行包括数列中的一项 Ak(k<=100000) A k ( k <= 100000 )

总行数 T<=30 T <= 30

输出描述:

对于每一项 Ak A k ,输出一行包括一个正整数 k k 表示输入中数是数列的第几项。

示例1

2
3
5
8
13

输出

2
3
4
5
6

分析

本题题意很简单,问题在于,给定的k值过大,这个数列早就已经超过了 long long 的范围,因此我们采用 hash 的思想,给数列中的每一项做一个 id i d 映射到对应的下标。对于本题,我们可以选择若干个大质数(例如5个),质数选的越大越多就越不容易发生hash 冲突,求取 Ai(i100000) A i ( i ≤ 100000 ) 对5个大质数取模后的结果,然后对于每次询问,我们同样去模这些大质数,最后判断每个查询对应的质数取模数组和之前算过的某个是否完全相同,如果完全相同,则返回该下标即可。代码1是这样实现的。对于本题来说将 Ai(i100000) A i ( i ≤ 100000 ) 的值记为 Ai(i100000) A i ( i ≤ 100000 ) 的真实值对 long long 自然溢出的结果,也是可行的,可能是数据比较水吧。代码2是这样实现的。

//代码1
#include <bits/stdc++.h>
#define N int(1e5+5)
using namespace std;
typedef unsigned long long ll;
ll arr[N][6];
ll mod[5]={1000000007,1000000009,91815541,68861641,51646229};
ll t[5];
int main(void)
{
    for(int i = 0;i < 5;i ++){
        arr[1][i] = 1;
        arr[2][i] = 2;
    }
    for(int i = 3;i <= int(1e5);i ++){
        for(int j = 0;j < 5;j ++)
            arr[i][j] = (arr[i - 1][j] + arr[i - 2][j]) % mod[j];
    }
    string s;
    while(cin >> s){
        memset(t,0,sizeof(t));
        for(int i = 0;i < s.size();i ++)
            for(int j = 0;j < 5;j ++)
                t[j] = (t[j] * 10 + s[i] - '0') % mod[j];
        for(int i = 1;i <= int(1e5);i ++){
            bool ok = 1;
            for(int j = 0;j < 5;j ++){
                if(arr[i][j] != t[j]){
                    ok = 0;
                    break;
                }
            }
            if(ok){
                cout << i << endl;
                break;
            }
        }
    }
    return 0;
}
//代码2
#include <bits/stdc++.h>
#define N int(1e5+5)
using namespace std;
long long arr[N];
int main(void)
{
    arr[1] = 1;
    arr[2] = 2;
    for(int i = 3;i <= 1e5;i ++){
        arr[i] = arr[i - 1] + arr[i - 2];
    }
    string t;
    while(cin >> t){
        long long num = 0;
        for(int i = 0;i < t.size();i ++)
            num = num * 10 + t[i] - '0';
        for(int i = 1;i <= 1e5;i ++){
            if(arr[i] == num){
                cout << i << endl;
                break;
            }
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值