原文:http://blog.acmj1991.com/?p=616
题意:给你n头牛,同时每头牛不多于m种的特征。然后给你n个数第i个数表示第i头牛的特征,这个数的二进制的第j位表示第i头牛是否有第j个特征。题目要求一个最大的连续的牛,这些牛的每个特征的总和相等
思路:要想每种特征的总和相等就相当于把多余的特征去掉,因此我们首先得找到前j项之和对2^m-1取余相等的数,所以对取余后的数进行hash,并且用数组存下前j想每个特征的总和
#include<stdio.h>
#include<string.h>
#define maxN 100010
#define A 1000000
int dp[maxN],head[A+10],key[40],h;
struct poin{
int s[35],next;
}po[maxN];
int min(int x,int y){return x<y?x:y;}
int max(int x,int y){return x>y?x:y;}
int query(int x,int i)
{
int j,m=head[x%A],minn=key[30];
if(m==-1){
po[i].next=-1,head[x%A]=i;
return i;
}
while(1)
{
if(dp[m]==x){
int len=po[i].s[0]-po[m].s[0];
for(j=0;j<h;j++)
if(po[i].s[j]-po[m].s[j]!=len)break;
if(j==h)minn=min(minn,m);
}
if(po[m].next==-1)break;
m=po[m].next;
}
po[i].next=po[m].next;
po[m].next=i;
return minn==key[31]?i:minn;
}
int main()
{
int n,m,a;
memset(head,-1,sizeof(head));
memset(po,0,sizeof(po));
key[0]=1;
for(int i=1;i<=31;i++)
key[i]=key[i-1]*2;
scanf("%d%d",&n,&m);h=m;
m=key[m]-1;
int maxx=0;
query(0,0);
for(int k=1;k<=n;k++)
{
scanf("%d",&a);
for(int i=0;i<h;i++){
po[k].s[i]=po[k-1].s[i];
if(a&key[i])po[k].s[i]++;
}
dp[k]=(dp[k-1]+a)%m;
maxx=max(maxx,k-query(dp[k],k));
}
printf("%d\n",maxx);
}