开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第12天,点击查看活动详情
C - Binary Strings are Fun
题意:对于一个01串如果每一个奇数位上的数是前缀中的median,那么这个串就是好的,median的定义就是如果s[i]=1,那么前i个位置1的次数要多于0,如果s[i]=0,那么前i个位置0的次数要多于1。对于一个串的扩展字符串t,假设有一个长度为k的字符串,扩展字符串的长度就是2k-1,要求是s[i]=t[2i-1];对于给定的一个字符串s,对于s的每一个前缀,总共可以有多少个好的扩展字符串
思路:可以玩一遍样例,比如
9 101101111 a[2]表示0和1的个数
s[1,1] 有1个,rem=0
s[1,2] 0的个数小于等于1所以让t[2]=0,有1个,rem=0
s[1,3] 1的个数小于等于0所以让t[4]=1,有1个,rem=0
s[1,4] 1的个数本来就大于0的个数,所以t[6]可以随便选,有2个,rem=1
s[1,5],0的个数小于1,所以让t[6],t[8]=0,有1个,rem=0
s[1,6],1的个数小于0,t[10]=0,有1个,rem=0
s[1,7],1的个数本来就大于0,t[12]随便选,有2个,rem=1
s[1,8],1的个数本来就大于0,t[12],t[14]随便选,有4个,rem=2
s[1,9],1的个数本来就大于0,t[12],t[14],t[16]随便选,有6个,rem=3
加起来正好21,代码就是模拟这个过程就行
#include<bits/stdc++.h>
//#pragma-GCC-optimize("-Ofast");
#define ll long long
#define int long long
#define lowbit(x) ((x)&(-x))
#define endl '\n'
using namespace std;
const ll mod=998244353;
const ll inf=1e18;
const double pi=acos(-1);
const int N=1e6+100;
ll qpow(ll a,ll b)
{
ll res=1;
while(b)
{
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
ll getinv(ll a){return qpow(a,mod-2);}
int t,n,two[N],fac[N];
char s[N];
int C(int a,int b)
{
if(a<b||b<0) return 0;
return (fac[a]*getinv(fac[a-b])%mod)*getinv(fac[b])%mod;
}
signed main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
two[0]=1;fac[0]=1;
for(int i=1;i<=1000000;i++) two[i]=two[i-1]*2LL%mod,fac[i]=fac[i-1]*i%mod;
cin>>t;
while(t--)
{
int ans=0,a[2]={0,0},rem=0;
cin>>n;cin>>(s+1);
for(int i=1;i<=n;i++)
{
int j=i*2-1,x=s[i]-'0';
a[x]++;
if(i>1) rem++;
if(a[x]<i) rem-=i-a[x],a[x]=i;
ans=(ans+two[rem])%mod;
// cout<<"a[x]="<<a[x]<<" a[!x]="<<a[!x]<<" rem="<<rem<<" ans="<<ans<<endl;
}
cout<<ans<<endl;
}
return 0;
}