题解:CF2187D Cool Problem
人类真的可以想到吗?
改写一下条件,变成:
- 当
s_i=0 时,有c_i-\frac{x+y}{2}=c_{i-1}-\frac{y-x}{2} 。 - 当
s_i=1 时,有c_i-\frac{x+y}{2}=\frac{y-x}{2}-c_{i-1} 。
形式很类似了,唯一的不同是右边的正负性,考虑两边平方一下,于是统一起来了,变成:
化简可以得到:
很好看的限制,和
证明就是两边求
考虑用 DP 求出每个
注意到
具体地:
转移分类讨论即可,是简单的,最后用求出来的
:::success[code] 注意!计算过程中会爆 long long,并且 CF 的老年机不能用 int128,要用 int128_t!
#include<bits/stdc++.h>
#define int long long
#define Bs bitset<100007>
using namespace std;
const int N=1e6+7;
const int Mod=998244353;
int n,x,y;
inline int calc(int c)
{
__int128_t A=(__int128_t)c*c;
__int128_t B=(__int128_t)(x-y)*c;
__int128_t C=(__int128_t)n*x*y;
__int128_t D=(__int128_t)2*x;
__int128_t res=(A+B+C)/D;
return (int)res;
}
int top;
int st[N];
inline void solve()
{
cin>>n>>x>>y;
string s;
cin>>s;
Bs f0,f1,g0,g1;
f0[0]=g0[0]=1;
for(auto c:s)
{
Bs nf0,nf1,ng0,ng1;
if(c!='1')
{
nf0|=f0<<1;
nf1|=f1<<1;
ng0|=g0>>1;
ng1|=g1>>1;
}
if(c!='0')
{
nf0|=g1;
nf1|=g0;
ng0|=f1;
ng1|=f0;
}
nf0[0]=nf0[0]|ng0[0];
ng0[0]=ng0[0]|nf0[0];
nf1[0]=nf1[0]|ng1[0];
ng1[0]=ng1[0]|nf1[0];
f0=nf0,f1=nf1,g0=ng0,g1=ng1;
}
top=0;
for(int i=0;i<=n;i++)
{
if(f0[i])st[++top]=calc(i*x);
if(f1[i])st[++top]=calc(i*x+y);
}
for(int i=1;i<=n;i++)
{
if(g0[i])st[++top]=calc(-i*x);
if(g1[i])st[++top]=calc(-i*x+y);
}
sort(st+1,st+1+top);
int ans=0;
for(int i=1;i<=top;i++)
if(i==1||st[i]!=st[i-1])
ans=(ans+(st[i]%Mod+Mod))%Mod;
cout<<ans<<'\n';
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
int T;
cin>>T;
while(T--)solve();
}
:::