HDU 6046

思路来自题解和一些博客

最麻烦的是样例没啥用- -

/*
HDU 6046 - hash [ hash,鸽巢 ]  |  2017 Multi-University Training Contest 2
题意:
	给出一个1e3*1e3的矩阵以及 一个 生成1e6*1e6的矩阵的随机函数
	在1e6*1e6的矩阵中找到1e3*1e3的矩阵的位置
分析:
	将1e3*1e3的矩阵每一个位置压入哈希表中,哈希值为其与之后63位所组成64位的值(不满64位就不压入)
	由于 2^64 远大于 1e12 故可认为哈希值相同的是同一个位置
	枚举大矩阵中的位置,若能在哈希表中找到这个位置的哈希值,则小矩阵头部的相对位置可以确定
	但不需要枚举大矩阵中的每个位置,可以每隔1000行,隔900列枚举一个位置
	这样根据鸽巢原理,枚举的这些位置至少有一个被小矩阵覆盖
	
	选隔900列而不是1000列的原因是 小矩阵每行最右端63个点没被压入哈希表,所以哈希表中的矩阵是 1000 * (1000-63)的
*/
#include <bits/stdc++.h>
using namespace std;
#define LL unsigned long long
const int N = 1e3+5;
const int L = 1000;
const int ZIP = 64;
inline unsigned sfr(unsigned h, unsigned x) {
  return h >> x;
}
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;
}
namespace HashMap{
    const int MOD = 1313131;
    struct Node {
        LL pos, val;
        int nxt;
    }node[N*N];
    int head[MOD], tot;
    void init() {
        memset(head, 0, sizeof(head));
        tot = 0;
    }
    void insert(LL v, LL p) {
        int t = v % MOD; tot++;
        node[tot].pos = p;
        node[tot].val = v;
        node[tot].nxt = head[t];
        head[t] = tot;
    }
    LL find(LL v) {
        for (int i = head[v%MOD]; i; i = node[i].nxt)
            if (node[i].val == v) return node[i].pos;
        return 0;
    }
}
char s[N];
LL hs[N];
int main()
{
    int t; scanf("%d", &t);
    for (int tt = 1; tt <= t; tt++)
    {
        HashMap::init();
        for (int i = 1; i <= L; i++)
        {
            scanf("%s", s+1);
            hs[L+1] = 0;
            for (int j = L; j >= 1; j--)
                hs[j] = hs[j+1]<<1|(s[j]-'0');
            for (int j = 1; j <= L-ZIP+1; j++)
                HashMap::insert(hs[j], i*1024+j);
        }
        LL ans = 0; int x, y;
        for (int i = 1; i <= 1e6 && (!ans); i += 1000)
            for (int j = 1; j <= 1e6 && (!ans); j += 900)
            {
                if (j+ZIP-1 > 1e6) continue;
                LL val = 0;
                for (int k = ZIP-1; k >= 0; k--)
                    val = val<<1|(f(i,j+k));
                ans = HashMap::find(val);
                if (ans != 0) x = i, y = j;
            }
        int px = x - ans / 1024 + 1, py = y - ans % 1024 + 1;
        printf("Case #%d :%d %d
", tt, px, py);
    }
}

  

我自倾杯,君且随意
原文地址:https://www.cnblogs.com/nicetomeetu/p/7286724.html