这题,首先,需要将每个数都转成二进制的。

对于每个二进制,做一遍前缀和,作为a[i][j]。

对于每一个a[i][j],减去a[i][1],这样子,如果a[x][j]==a[y][j](j=1...m)都相等。

那么这就是一对可行解。

对于每一个a[i][1...n]将其哈希。即可。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 inline int read(){
 7     int num=0,t=1;char c=getchar();
 8     while(c>'9'||c<'0'){if(c=='-')t=-1;c=getchar();}
 9     while(c<='9'&&c>='0'){num=(num<<1)+(num<<3)+c-'0';c=getchar();}
10     return num*t;
11 }
12 const int mod=1000007,N=100010;
13 int a[N][33],ans=0,m,n,cnt=0;
14 int ha[mod],g[N][33],nxt[N],fir[N];
15 void ins(int x,int y){
16     for(int i=ha[x];;i=nxt[i])
17         if(!i){ 
18             nxt[++cnt]=ha[x];ha[x]=cnt;fir[cnt]=y;
19             for(int j=1;j<=m;j++)g[cnt][j]=a[y][j];
20             break;
21         }
22         else{
23             int j;
24             for(j=1;j<=m;j++)if(g[i][j]!=a[y][j])break;
25             if(j>m)break;
26         }
27 }
28 int find(int x,int y){
29     for(int i=ha[x];i;i=nxt[i]){
30         int j;
31         for(j=1;j<=m;j++)if(g[i][j]!=a[y][j])break;
32         if(j>m)return y-fir[i];
33     }
34     return 0;
35 }
36 int main()
37 {
38     n=read();m=read();
39     for(int i=1;i<=n;i++){
40         int x=read();
41         for(int j=1;j<=m;j++)
42             a[i][j]=a[i-1][j]+((x>>(j-1))&1);
43         for(int j=m;j>=1;j--)
44             a[i][j]-=a[i][1];
45     }
46     ins(0,0);
47     for(int i=1;i<=n;i++){
48         int tot=0;
49         for(int j=1;j<=m;j++)tot=(tot+(a[i][j]%mod+mod)*j)%mod;
50         ins(tot,i);ans=max(ans,find(tot,i));
51     }
52     printf("%d",ans);
53     return 0;
54 }

注意,对于第43行的for循环,为什么要倒着做呢?因为,如果a[i][1]先减完之后,变成0了,可是呢,这样使得a[i][j](j>1)的值都不会更改。

本文由Yzyet编写,网址为www.cnblogs.com/Yzyet。非Yzyet同意,禁止转载,侵权者必究。

posted on 2017-09-14 21:12  Yzyet  阅读(211)  评论(0编辑  收藏  举报