兩道(疑似)哈希的題

2018.2.5 新生訓練Week3 E.密碼碰撞


EOJ 的登錄系統爆出了一個重大問題,當正確的密碼是你輸入的密碼的子串時,就可以成功登錄!

例如你的密碼是 abc,則你輸入 abcc,aabc,甚至 dfjklsdfabcsdjfkl,都可以成功登錄!

出現了這麼大的問題,那就一定要有人來背鍋,管理員們希望在背鍋之前先衡量一下鍋的大小。

現在有一份 EOJ 用戶的密碼錶,裏面包含了 n 個用戶的密碼,第 i 個用戶的密碼是 pwdi。我們定義鍋的大小爲所有有序對 (i,j) (i≠j) 的數量,使得用戶 i 能夠輸入他的密碼 pwdi 成功登陸用戶 j 的賬戶。

換句話說,我們現在需要知道,有多少有序對 (i,j) (i≠j) 使得 pwdj 是 pwdi 的子串。

第 1 行包含一個整數 n,1≤n≤20 000,表示密碼錶中密碼的數量。
第 1+i (1≤i≤n) 行包含一個長度不超過 10 且由小寫字母組成的字符串,表示 pwdi。

說明


因爲長度太短了,所以可以直接枚舉子串(每個密碼最多55個子串),hash一下存進map裏統計子串的出現次數。然後對於每個密碼,計算其在子串中出現的次數。記得要減去n,因爲每個密碼也一定是自己的子串。

#include <bits/stdc++.h>
using namespace std;

const int maxn = 20005;
typedef long long ll;
ll SS[maxn];
set<ll> S[maxn];
map<ll, int> m;
char s[15];
int n, ans, len;

int main()
{
    cin >> n;
    for (int i = 0; i < n; ++i)
    {
        scanf("%s", s);
        len = strlen(s);
        for (int j = 0; j < len; ++j)
        {
            ll h = 0;
            for (int k = j; k < len; ++k)
            {
                h = h * 29 + s[k]-'a'+1;
                S[i].insert(h);
                if (!j && k+1 == len) SS[i] = h;
            }
        }
        for (auto x: S[i]) ++m[x];
    }
    for (int i = 0; i < n; ++i)
        ans += m[SS[i]];
    printf("%d\n", ans-n);
    return 0;
}

2018.2.12 新生訓練Week4 D.斐波那契數列


有一個數列 An ,其中 A1=1,A2=2,An+2=An+1+An
給你一個數字,問他是這個數列的第幾項。
每行包括數列中的一項 Ak (k≤100000)。
總行數 T≤100。

說明


看到標題以爲是很水的題……
實際上,斐波那契數列的100000項是一個超出long long範圍的數,因此一開始考慮用高精度。後來發現數據加強了,時限和內存又比較緊(卡掉了我的python預處理算法&&python滾動暴力算法&&C++高精度+二分查找算法),只能使用一些技巧。
類似hash,用一個大質數(比如19260817)將斐波那契數列的各項hash掉,再利用同餘定理查找答案,就做完了……?

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1e5+5;
const int p = 19260817;
int now, f[maxn];
map<int, int> m;
string s;

int main()
{
    f[0] = f[1] = 1;
    m[1] = 1;
    for (int i = 2; i < maxn; ++i)
    {
        f[i] = (f[i-1] + f[i-2]) % p;
        m[f[i]] = i;
    }
    while (cin >> s)
    {
        now = 0;
        for (auto &i: s)
            now = (now*10 + i-'0') % p;
        printf("%d\n", m[now]);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章