zoukankan      html  css  js  c++  java
  • 【ZJOI2009】对称的正方形

    题面

    https://www.luogu.org/problem/P2601

    题解

    二维哈希(和二维前缀和类似)

    右向量:$107$
    下向量:$233$

    才不会取名叫$wls$和$wym$

    upd:突然想到,取$wls$和$wym$也挺好的,因为他们作为两个基向量,被我期待在任何一点永不相交。

    讽刺的是,现实生活中,他们一个在一中,一个在七中,竟然还能谈成。。。这说明我的哈希是失败的。

    想起了合肥市第四十五中学2015级4班著名作家$lyh$曾经写的一篇循环周记,讽刺这件事:

    一个猎人打猎,打到了一匹小马(我这么喊她),试图让小马当自己的坐骑,然后小马桀骜不驯,为了追求自由,自杀身亡。

    可惜当年,我还能被他们形容成猎人这个虽然邪恶但是充满力量的人物,还是很看得起我的,现在,估计当年的马尥一下蹶子就把我踹死了吧。现在的八中人,也没有人这么说吧($wym$在七中前$50$名,我在八中$1000$名)

    不想这些无聊的东西了,我还是好好想我女神吧。好在我女神还是一中前$50$的,女神最可爱啦。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #define N 1050
    #define ri register int
    #define uLL unsigned long long
    using namespace std;
    
    const uLL p1=107,p2=233;
    uLL pp1[N],pp2[N];
    int n,m;
    int a[N][N];
    
    struct hash{
      uLL sum1[N][N],sum2[N][N],sum3[N][N],sum4[N][N];
      void init() {
        for (ri i=1;i<=n;i++)
          for (ri j=1;j<=m;j++) 
            sum1[i][j]=sum1[i-1][j]*p1+sum1[i][j-1]*p2-sum1[i-1][j-1]*p1*p2+(uLL)a[i][j];
        for (ri i=n;i>=1;i--)
          for (ri j=1;j<=m;j++)
            sum2[i][j]=sum2[i+1][j]*p1+sum2[i][j-1]*p2-sum2[i+1][j-1]*p1*p2+(uLL)a[i][j];
        for (ri i=1;i<=n;i++)
          for (ri j=m;j>=1;j--)
            sum3[i][j]=sum3[i-1][j]*p1+sum3[i][j+1]*p2-sum3[i-1][j+1]*p1*p2+(uLL)a[i][j];
        for (ri i=n;i>=1;i--)
          for (ri j=m;j>=1;j--) 
            sum4[i][j]=sum4[i+1][j]*p1+sum4[i][j+1]*p2-sum4[i+1][j+1]*p1*p2+(uLL)a[i][j];
      }
      
      uLL s1(int a,int b,int x,int y){
        return sum1[x][y]-sum1[a-1][y]*pp1[x-a+1]-sum1[x][b-1]*pp2[y-b+1]+sum1[a-1][b-1]*pp1[x-a+1]*pp2[y-b+1];
      }
      uLL s2(int a,int b,int x,int y){
        return sum2[x][y]-sum2[a+1][y]*pp1[a-x+1]-sum2[x][b-1]*pp2[y-b+1]+sum2[a+1][b-1]*pp1[a-x+1]*pp2[y-b+1];
      }
      uLL s3(int a,int b,int x,int y){
        return sum3[x][y]-sum3[a-1][y]*pp1[x-a+1]-sum3[x][b+1]*pp2[b-y+1]+sum3[a-1][b+1]*pp1[x-a+1]*pp2[b-y+1];
      }
      uLL s4(int a,int b,int x,int y){
        return sum4[x][y]-sum4[a+1][y]*pp1[a-x+1]-sum4[x][b+1]*pp2[b-y+1]+sum4[a+1][b+1]*pp1[a-x+1]*pp2[b-y+1];
      }
      int check1(int x,int y) {
        int lb=1,rb=min(min(x-1,y-1),min(n-x,m-y));
        int ret=0;
        while (lb<=rb) {
          int mid=(lb+rb)/2;
          uLL t1=s1(x-mid,y-mid,x,y);
          uLL t2=s2(x+mid,y-mid,x,y);
          uLL t3=s3(x-mid,y+mid,x,y);
          uLL t4=s4(x+mid,y+mid,x,y);
          if (t1==t2 && t2==t3 && t3==t4) ret=mid,lb=mid+1; else rb=mid-1;
        }
        return ret+1;
      }
      int check2(int x,int y) {
        int lb=1,rb=min(min(x-1,y-1),min(n-1-x,m-1-y));
        int ret=0;
        while (lb<=rb) {
          int mid=(lb+rb)/2;
          uLL t1=s1(x-mid,y-mid,x,y);
          uLL t2=s2(x+1+mid,y-mid,x+1,y);
          uLL t3=s3(x-mid,y+1+mid,x,y+1);
          uLL t4=s4(x+mid+1,y+mid+1,x+1,y+1);
          if (t1==t2 && t2==t3 && t3==t4) ret=mid,lb=mid+1; else rb=mid-1;
        }
        return ret+1;
      }
    } H;
    int main(){
      pp1[0]=1; pp2[0]=1;
      for (ri i=1;i<N;i++) pp1[i]=pp1[i-1]*p1,pp2[i]=pp2[i-1]*p2;
      scanf("%d %d",&n,&m);
      for (ri i=1;i<=n;i++) 
        for (ri j=1;j<=m;j++) scanf("%d",&a[i][j]);
      H.init();
      int ans=0;
      for (ri i=1;i<=n;i++) 
        for (ri j=1;j<=m;j++) {
          ans+=H.check1(i,j);
          if (a[i][j]==a[i+1][j] && a[i+1][j]==a[i][j+1] && a[i][j+1]==a[i+1][j+1]) ans+=H.check2(i,j);
        }
      cout<<ans<<endl;
    }
  • 相关阅读:
    【UNIX环境高级编程】线程同步
    死锁
    Shell Script的默认变量
    高通平台读写nv总结
    PLMN概念和应用设置
    win10间歇性的找不到usb设备
    (转)查询或修改iPhone的短信服务中心号码(iOS通用)
    (转)CS域和PS域
    SSL&HTTPS简单介绍
    WAV和PCM的关系和区别
  • 原文地址:https://www.cnblogs.com/shxnb666/p/11279773.html
Copyright © 2011-2022 走看看