poj3274(数字hash)

来源:互联网 发布:json格式转换 编辑:程序博客网 时间:2024/05/01 19:50

链接:点击打开链接

题意:给出n个数,找出一个最长的区间使得,区间内每个数变为二进制后,每一位的1的个数和相同

代码:

#include <set>#include <map>#include <queue>#include <stack>#include <string>#include <vector>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <iostream>#include <algorithm>using namespace std;const int MOD=99991;const int siz=100005;vector<int> G[siz];int n,k,s[siz][35],sum[siz][35];int judge(int x,int y){    int i,tmp;    tmp=sum[x][0]-sum[y][0];    for(i=1;i<k-1;i++)    if(sum[x][i]-sum[y][i]!=tmp)    return 0;    return 1;}int main(){    int i,j,u,ans,tmp;    while(scanf("%d%d",&n,&k)!=EOF){            //当第i行和第j行每一位的前缀和相同时,        memset(s,0,sizeof(s));                  //第i行和第j行每相邻两个数的差所组成的数列        memset(sum,0,sizeof(sum));              //也一定相同,所以问题就变为求两个相同序列        for(i=0;i<siz;i++)                      //的最远距离,直接hash一下        G[i].clear();        for(i=1;i<=n;i++){            scanf("%d",&u);            for(j=0;j<k;j++){                if(u&(1<<j))                sum[i][j]=1;            }        }        if(k==1){                               //k=1输出n            printf("%d\n",n);            continue;        }        for(i=2;i<=n;i++){            for(j=0;j<k;j++){                sum[i][j]+=sum[i-1][j];            }        }        ans=0;        for(i=n;i>=1;i--){                      //判断能否从一开始一直相同            for(j=1;j<k;j++)            if(sum[i][j]!=sum[i][0])            break;            if(j==k){                ans=i;                break;            }        }        for(i=1;i<=n;i++){            tmp=0;            for(j=0;j<k-1;j++){                s[i][j]=sum[i][j+1]-sum[i][j];                tmp+=s[i][j];            }            tmp=(tmp+MOD)%MOD;            for(j=0;j<G[tmp].size();j++){                if(judge(i,G[tmp][j]))                ans=max(ans,i-G[tmp][j]);            }            G[tmp].push_back(i);        }        printf("%d\n",ans);    }    return 0;}

原创粉丝点击