POJ 3274 Hash

题意:
这里写图片描述

思路:
先把每个区间的前缀和搞出来 为sum[i][j]

然后我们发现

对于一段 每个前缀和之差是定值的情况

都减去 sum[i][0] 是同一个数

所以我们就Hash一遍 判一判

hash到同一个数的时候check一下 就OK了

//By SiriusRen
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define mod 1000007
int n,k,a[100050][32],sum[100050][32],st[100050],vis[2005007],ans;
bool check(int st,int ed){
    for(int j=0;j<k;j++){
        if(sum[st][j]!=sum[ed][j])return 0;
    }
    return 1;
}
signed main()
{
    memset(vis,-1,sizeof(vis));
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)scanf("%d",&st[i]);
    for(int i=1;i<=n;i++){
        for(int j=0;j<k;j++){
            if(st[i]&(1<<j))a[i][j]=1;
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=0;j<k;j++){
            sum[i][j]=sum[i-1][j]+a[i][j];
        }
    }
    for(int i=1;i<=n;i++){
        int tmp=sum[i][0];
        for(int j=k-1;j>=0;j--){
            sum[i][j]=sum[i][j]-tmp;
        }
    }
    vis[mod]=0;
    for(int i=1;i<=n;i++){
        int temp=0;
        for(int j=0;j<k;j++){
            temp=(temp*1007+sum[i][j])%mod;
        }
        if(vis[temp+mod]==-1){
            vis[temp+mod]=i;
        }
        else{
            if(ans<i-vis[temp+mod]){
                if(check(i,vis[temp+mod]))
                    ans=i-vis[temp+mod];
            }
        }
    }
    printf("%d\n",ans);
}

这里写图片描述

posted @ 2016-10-12 07:55  SiriusRen  阅读(88)  评论(0编辑  收藏  举报