CF1383E Strange Operation 题解
RedLycoris · · 题解
题目大意:
给你一个长度为
每一次操作,可以选择一个位置(不为最后一位),然后删除它和它后面一位,在原来的位置上填上他们的或。每次操作会使
问你执行最多
题解:
根据套路,就可以把相同的数分成一段一段的。又因为是或,所以我们可以认为
考虑操作过程:
如果选择的是两个
反之,删除的肯定是一个
然后我们就相当于:统计数组
吗?
不,这题不会这么简单,因为很显然会重复计算。
所以,我们考虑怎么去重:
前面推的时候,对于选择了两个
我们对这一块重新考虑下。
令
为了去重,当
处理
最后用前缀和优化把复杂度从
Code:
string s;
const int mxn=1e6+6;
int cnt[mxn],m,n;
const ll md=1000000007;
ll sum[mxn],dp[mxn];
int pos[mxn];
inline void add(ll&x,ll y){
x+=y;
if(x>=md)x-=md;
if(x<0)x+=md;
if(x>=md)x-=md;
if(x<0)x+=md;
}
inline void solve(){
cin>>s;n=s.size();
s=s+"1";
for(int i=0,j=0;i<s.size();++i){
for(;j<s.size() and s[j]=='0';)++j;
// cerr<<"? "<<i<<' '<<j<<'\n';
cnt[++m]=j-i;
i=j;
j=i+1;
}
if(m==1){
cout<<n<<'\n';
return;
}
// for(int i=1;i<=m;++i)cerr<<cnt[i]<<' ';cerr<<'\n';
ll ans=(cnt[1]+1)*1ll*(cnt[m]+1)%md;
sum[1]=1,dp[1]=1;
for(int i=1;i<=n;++i)pos[i]=1;
for(int i=2;i<m;++i){
for(int j=0;j<=cnt[i];++j)add(dp[i],sum[i-1]-sum[pos[j]-1]);
for(int j=0;j<=cnt[i];++j)pos[j]=i;
add(sum[i],sum[i-1]+dp[i]);
}
cout<<(ans*1ll*sum[m-1])%md<<'\n';
}
int main(){
ios_base::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int T=1;
//cin>>T;
for(;T--;)solve();
return 0;
}