solution
观察题目性质,首先可以得出:
设
p
i
p_i
pi 表示第
i
i
i 天的能力数字和,若
l
−
r
l-r
l−r 为一段均衡时间,则
2
m
−
1
∣
p
r
−
p
l
−
1
p
r
−
p
l
−
1
=
k
(
2
m
−
1
)
2^{m}-1|p_r-p_{l-1}\\ p_r-p_{l-1}=k(2^m-1)
2m−1∣pr−pl−1pr−pl−1=k(2m−1)
等同于:
设
p
i
,
j
p_{i,j}
pi,j 表示第
i
i
i 天数字和的第
j
j
j 位
∀
i
∈
[
1
,
m
]
,
p
r
,
i
−
p
l
−
1
,
i
=
k
\forall i\in[1,m] ,p_{r,i}-p_{l-1,i}=k
∀i∈[1,m],pr,i−pl−1,i=k
接下来对其进行变形
p
r
,
i
−
p
l
−
1
,
i
=
k
=
p
r
,
1
−
p
l
−
1
,
1
p
r
,
i
−
p
r
,
1
=
p
l
−
1
,
i
−
p
l
−
1
,
1
p_{r,i}-p_{l-1,i}=k=p_{r,1}-p_{l-1,1}\\ p_{r,i}-p_{r,1}=p_{l-1,i}-p_{l-1,1}
pr,i−pl−1,i=k=pr,1−pl−1,1pr,i−pr,1=pl−1,i−pl−1,1
于是我们成功将于
r
,
l
−
1
r,l-1
r,l−1 有关的部分分开了
显然此结论可以逆推
感性理解,若两数与首个数的差都相同,则两数之间的差也与首个数之间的差相同
于是我们得到了判定两个数字和是否合法的仅与数字和本身有关的方法,于是可以考虑哈希
对于每一天处理出前缀数字和,再维护出每一个 p i , j − p i , 1 p_{i,j}-p_{i,1} pi,j−pi,1 用最前的更新最大值即可。
示例代码
#include<bits/stdc++.h>
#define ll long long
#define N 100005
#define inf 1000000007
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fd(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
int n,m,ans,ipr[N];
map<vector<ll>,int> mp;
vector<ll> u,v;
int read(){
int res=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-'&&((ch=getchar())>='0'&&(ch)<='9')) f=-1;
else ch=getchar();
}
while(ch>='0'&&ch<='9')res=res*10+ch-'0',ch=getchar();
return res*f;
}
int main(){
n=read(),m=read();
fo(i,0,m-1){
if(i)v.push_back(0);
u.push_back(0);
}
mp[v]=1;
fo(i,1,n){
v.clear();
ipr[i]=read();
fo(j,0,m-1){
if(ipr[i]&(1<<j))u[j]+=1;
if(j)v.push_back(u[j]-u[0]);
}
if(!mp[v])mp[v]=i+1;
else ans=max(ans,i+1-mp[v]);
}
printf("%d",ans);
}