题解
题目大意 给你一个hash函数 传入横纵坐标得到一个1e6*1e6的矩阵 给你1e3*1e3的子矩阵问在大矩阵的哪个位置 输出左上角坐标
将1*64的横条状矩阵作为一个单位(2^64足够大并且方便hash) 对小矩阵每个位置都取的单位矩阵hash 将对应位置存入hash表
根据抽屉原理 对大矩阵每隔1000行1000-63列抽取一个单位矩阵并计算hash(这样不管怎么抽都能抽到小矩阵中的一个)并用hash表找找到出现位置并输出
不手写hash表直接用unordered_map也是可以 只是没手写的快
AC代码
#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e6 + 3; //素数
char s[MAXN];
struct HashTable
{
struct node
{
ull key, val;
int nxt;
}elem[MAXN]; //存储元素
int head[MAXN], tot; //head存储每个位置的第一个元素编号
void Init()
{
tot = 0;
memset(head, -1, sizeof(head));
}
void Push(ull key, ull val)
{
int k = key % MAXN; //取模位置
for (int i = head[k]; ~i; i = elem[i].nxt)
if (elem[i].key == key) //key相等
{
elem[i].val += val; //已有+val
return;
}
elem[tot] = { key, val, head[k] }; //将原有接在后面
head[k] = tot++; //head记录当前
}
ull Find(ull key)
{
int k = key % MAXN; //取模位置
for (int i = head[k]; ~i; i = elem[i].nxt)
if (elem[i].key == key) //key相等
return elem[i].val;
return 0;
}
}ht;
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;
}
void solve()
{
ht.Init();
int n = 1e6, m = 1e3; //大小矩阵大小
for (int i = 1; i <= m; i++)
{
scanf("%s", s + 1);
ull key = 0; //将横着64个数值压缩到ull
for (int j = 1; j < 64; j++) key = key << 1 | (s[j] == '1');
for (int j = 64; j <= m; j++) //从第64个开始向hash表插入
{
key = key << 1 | (s[j] == '1');
ht.Push(key, (i - 1) * m + j - 64); //对应key存储位置 坐标-1
}
}
for (int i = 1; i <= n; i += m) //根据抽屉原理每隔一段计算一个
for (int j = 1; j + 63 <= n; j += m - 63)
{
ull key = 0;
for (int k = 0; k < 64; k++) key = key << 1 | f(i, j + k);
int pos = ht.Find(key);
if (pos)
{
cout << (i - pos / m) << " " << (j - pos % m) << endl;
return;
}
}
}
int main()
{
#ifdef LOCAL
freopen("C:/input.txt", "r", stdin);
#endif
int T;
cin >> T;
for (int ti = 1; ti <= T; ti++)
printf("Case #%d :", ti), solve();
return 0;
}