http://acm.hdu.edu.cn/showproblem.php?pid=6046
又是18徐州第一题,所有数字都不同,又不会用这个性质我吐了
因为给出的函数是完全随机,所以所有数字排列都完全随机,而2^64-1刚好是ull,那么我们可以认为任意不同位置的8*8的矩阵的数字排列也是完全不同的,我们就可以隔980就搞个8*8的矩阵把他记录下来存进map,由于任意一个1000*1000的矩阵中任意两个8*8矩阵之间最多差984,那么这其中必有一个我们之前存了的8*8的矩阵,直接枚举所有的找到一个就行了
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int up=1e6;
const int maxl=1010;
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;
}
int n,ansx,ansy,cas;
ull mi[100];
unordered_map<ull,int> mpx,mpy;
int a[maxl][maxl];
char s[maxl];
inline void init()
{
mi[1]=1;
for(int i=2;i<=64;i++)
mi[i]=mi[i-1]*2;
ull d;int tot;
for(register int i=1;i+8-1<=up;i+=980)
for(register int j=1;j+8-1<=up;j+=980)
{
d=0;tot=0;
for(register ll x=0;x<8;++x)
for(register ll y=0;y<8;++y)
{
++tot;
if(f(i+x,j+y))
d|=mi[tot];
}
mpx[d]=i;mpy[d]=j;
}
}
inline void prework()
{
n=1000;
for(int i=1;i<=n;i++)
{
scanf("%s",s+1);
for(int j=1;j<=n;j++)
if(s[j]=='1')
a[i][j]=1;
else
a[i][j]=0;
}
}
inline void mainwork()
{
ull d;int tot;
for(int i=1;i<=1000-7;i++)
for(int j=1;j<=1000-7;j++)
{
d=0;tot=0;
for(ll x=0;x<8;x++)
for(ll y=0;y<8;y++)
{
++tot;
if(a[i+x][j+y])
d|=mi[tot];
}
if(mpx[d]!=0)
{
ansx=mpx[d]-i+1;
ansy=mpy[d]-j+1;
return;
}
}
}
inline void print()
{
++cas;
printf("Case #%d :%d %d\n",cas,ansx,ansy);
}
int main()
{
int t;init();
scanf("%d",&t);
for(int i=1;i<=t;i++)
{
prework();
mainwork();
print();
}
return 0;
}