先说题意把,从网上找到了一个能很好解释题意的图片
下面我以此题举个例子
此题的输入如下
7 3
7
6
7
2
1
4
2
也就是说有7头牛
将下面输入的7个数字每个数字都可以先转化内位数不超过3位的二进制数(注意顺序是从右向左)
先来转一下
1 2 3 序号
7 1 1 1 1
6 0 1 1 2
7 1 1 1 3
2 0 1 0 4
1 1 0 0 5
4 0 0 1 6
2 0 1 0 7
举个例子来说明要求什么,从序号3到序号6之间
对应1的共有两个,对应2的共有两个,对应3的共有两个
也就是说此时的距离为6-3+1=4
我们要求的是最长的距离
1 2 3 序号
7 1 1 1 1
6 1 2 2 2
7 2 3 3 3
2 2 4 3 4
1 3 4 3 5
4 3 4 4 6
2 3 5 4 7
上面图的意思是
设立一个数组sum[i][j]
i代表行数,j代表列数
sum代表从第一行的j列到第i行的j列中,j列共包含多少个1
我们发现当sum[j][1]-sum[i][1]=sum[j][2]-sum[i][2]=sum[j][3]=sum[i][3]的时候
存在一个(j-i+1)的区域长度符合条件。
我们把等式转换一下
sum[j][2]-sum[j][1]=sum[i][2]-sum[i][1]
sum[j][3]-sum[j][1]=sum[i][3]-sum[i][1]
下面是示例图(减去第一列)
1 2 3 序号
7 0 0 0 1
6 0 1 1 2
7 0 1 1 3
2 0 2 1 4
1 0 1 0 5
4 0 1 1 6
2 0 2 1 7
基本上讲解到这里题意已经很清楚了,接下来用哈希表将sum[i][]和sum[j][]相同的存在一个哈希函数里
比如3和6对应一个哈希函数,存到对应哈希函数的vector里
最后我们查找哈希函数里区间最大的值作答案。
下面是代码实现
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
#define prime 501
int c[100001][35],sum[100001][35];
int n,k;
int Max=0;
vector<int>ha[505];
bool cmp(int x,int y)
{
for(int i=1; i<=k; ++i)
{
if(c[x][i]!=c[y][i])
return false;
}
return true;
}
int main()
{
int l;
long long x;
cin>>n>>k;
for(int i=1; i<=n; ++i)
{
scanf("%lld",&x);
for(int j=1; j<=k; ++j)
{
l=x%2;
x=x/2;
sum[i][j]=sum[i-1][j]+l;
}
}
for(int i=1; i<=n; ++i)
{
int su=0;
int tot=0;
for(int j=1; j<=k; ++j)
{
c[i][j]=sum[i][j]-sum[i][1];
if(!c[i][j])tot++;
su=(su+c[i][j])%prime;
}
su=abs(su);
if(tot==k && i>Max)Max=i;
ha[su].push_back(i);
}
for(int i=0; i<prime; ++i)
{
int len=ha[i].size();
if(len>1)
{
for(int j=0; j<len-1; ++j)
for(int m=j+1; m<len; ++m)
{
int l=ha[i][m]-ha[i][j];
if(l>Max&&cmp(ha[i][j],ha[i][m]))
{
Max=l;
}
}
}
}
cout<<Max<<endl;
}