HDU6046 hash 【2017多校联训第二场B】

来源:互联网 发布:如何利用网络做直销 编辑:程序博客网 时间:2024/06/10 15:51

传送门
题目大意:给出一个106106的矩阵的每一位的计算方式,然后给出一个103103的矩阵,求这个矩阵出现的位置。
题解:对于小矩阵的每一个位置求出这个位置以及之后63位的值压在一个unsigned long long里面。因为这个大矩阵是完全随机的,而且264远大于1012所以我们可以认为,只要压的那个64位的unsigned long long相同,就是同一个位置。所以我们现在已经有了一个手段,猜任意一个位置,我们能判断是不是在小矩阵中。所以我们就可以开始枚举位置。但是显然我们一个一个地枚举位置是不可取的,所以枚举是需要技巧的,我们可以以1000为基数跳着寻找下一个位置,然后总的时间复杂度就是O((106103)264)
看不懂就看看代码吧,表达能力捉鸡……

#include <bits/stdc++.h>const int MAXN = 1e3 + 5, MXM = 1e6;const int L = 1e3, ZIP = 64;#define LL unsigned long longusing namespace std;inline unsigned sfr(unsigned h, unsigned x) {    return h >> x;}inline unsigned Ran() {    return rand() << 15 | rand();}int f(LL i, LL j) {    LL w = i * 1000000ll + j;    int h = 0;    for(int k = 0; k < 5; ++k) {        h += (int) ((w >> (8 * k)) & 255);        h += (h << 10);        h ^= sfr(h, 6);    }    h += h << 3;    h ^= sfr(h, 11);    h += h << 15;    return sfr(h, 27) & 1;}const int MOD = 1313131;struct HashMap {    int adj[MOD], cc, nxt[MAXN * MAXN];    LL val[MAXN * MAXN], pos[MAXN * MAXN];    void clr() { memset(adj, 0, sizeof adj); cc = 0; }    inline void Ins(LL v, LL p) {        int t = v % MOD; ++ cc;        val[cc] = v; pos[cc] = p; nxt[cc] = adj[t]; adj[t] = cc;    }    inline LL Find(LL v) {        int u = v % MOD;        for(int i = adj[u]; i; i = nxt[i])            if(val[i] == v) return pos[i];        return 0;    }} mp;char s[MAXN];LL hsh[MAXN];int main () {    int T;    scanf("%d", &T);    for(int Cas = 1; Cas <= T; ++ Cas) {        for(int i = 1; i<=L; i++) {            scanf("%s", s+1);            for(int j = 1; j <= L; j++) {                hsh[j] = (hsh[j-1]<<1)+(s[j]=='1');            }            for(int j = 1; j<=(L-ZIP+1); j++)                mp.Ins(hsh[j+ZIP-1], 1000001LL*i+j);        }        LL ans = 0; int px, py;        for(int i = 1; (!ans) && i <= MXM; i += 1000)            for(int j = 1; (!ans) && j <= MXM; j += 900) {                if(j+ZIP-1 > MXM) continue ;                LL hsh = 0;                for(int t = 0; t<ZIP; t++)                    hsh = (hsh<<1) + f(i, j+t);                if((ans=mp.Find(hsh)) != 0) {                    px = i, py = j; break;                }            }        int x = ans / 1000001ull, y = ans % 1000001ull;        printf("Case #%d :%d %d\n", Cas, px-x+1, py-y+1);        if(Cas != T) mp.clr();    }}
原创粉丝点击