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