hdu6046 hash 2017多校2

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;
}

猜你喜欢

转载自blog.csdn.net/liufengwei1/article/details/109005304