前言
逆天计数坐牢局,上来一看10道题全mod 998244353,就知道不对劲。大约前3小时我和队友们在轮番思考除DFJ以外的所有题(我甚至试了无数种dp方法写A,赛后一看题解直接傻眼),后面开始专攻BGI。4小时多,队友开出了B,比赛快结束的时候,我终于过掉了I。赛后我一边看题解一边看队友代码研究B,然而题解有点简略,我一晚上没看懂……今天终于懂了,来写一篇详细的题解。
我真傻,真的。
B. Bit Operation
题意
给定一个01序列a,可以执行n-1次如下操作:选择相邻的两个数a[i]和a[i+1],将它们替换为a[i] & a[i+1]或a[i] | a[i+1](这是两种不同的操作)。问有多少种方案,可以使最后剩下的那一个数是1。
解法
考虑题中给出的操作,选定的两个数只有四种可能的情况:
0 & 0 = 0, 0 | 0 = 0
1 & 1 = 1, 1 | 1 = 1
0 & 1 = 0, 0 | 1 = 1
1 & 0 = 0, 1 | 0 = 1
可以发现,如果两个数有0有1,&可以看作删掉其中的1,|可以看作删掉其中的0;如果两个数相同,&可以看作取左边的数,|可以看作取右边的数(当然,左右反过来也一样)。那么这个操作就可以等价于:
选择两个相邻的数,删掉其中一个;删左和删右是两种不同的操作。
这样就可以枚举a中每一个1,作为最后留下来的数。接下来考虑把选定的位置左右两端的所有数全部删掉的方案数。先考虑删除a[i](i不是选定的位置)的方案数。如果i=1,那么只能取a[1]和a[2],删除a[1],也就是只有一种方案。i=n与此同理。否则,可以取a[i-1]和a[i],删除a[i],或者取a[i]和a[i+1],删除a[i],也就是有两种方案。即:删掉第一个数的方案只有一种,而删掉其他数的方案都有2种。
用p[i]表示选定位置的某一侧有i个数时,把它们全部删掉的方案数。显然,p[0] = 1。由上述结论,这一侧有i个数时,第一次操作有(1+2i)种选择。做完这次操作,还剩i-1个数,全部删掉的方案数就是p[i-1]。所以可以通过
p[0] = 1;
for(int i = 1; i <= n; i++){
p[i] = p[i - 1] * (i * 2 - 1);
}
得出删掉一侧任意个数的方案数(实际做题注意取模)。
由于左右两端的操作可以相互穿插,假设选定的位置是i,那也就是说总共做了n-1次操作,其中有i-1次是对左边进行的,所以答案要再乘上组合数C(n-1, i-1)。i位置的最终答案就是p[i-1] * p[n-i] * C(n-1, i-1)。最后把所有选定位置的答案加起来即可。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
const int N = 1e6 + 5;
const ll P = 998244353;
int n, a[N];
ll p[N], inv[N], c[N], ans;
ll fastpow(ll x, ll y){
ll ret = 1;
while(y){
if(y & 1) ret = ret * x % P;
x = x * x % P;
y >>= 1;
}
return ret;
}
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; i++){
scanf("%d", &a[i]);
}
//p[i]表示选定的数的某一侧有i个数时,删掉这些数的方案数
p[0] = 1;
for(int i = 1; i <= n; i++){
p[i] = p[i - 1] * (i * 2 - 1) % P;
}
//inv[i]是i的逆元
for(int i = 1; i <= n; i++){
inv[i] = fastpow((ll)i, P - 2);
}
//c[i]表示组合数C(n - 1, i)
c[0] = 1;
for(int i = 1; i <= n; i++){
c[i] = (c[i - 1] * (n - i) % P) * inv[i] % P;
}
//对每个a[i] = 1的位置求出答案
for(int i = 1; i <= n; i++){
if(a[i]){
ans = (ans + (p[i - 1] * p[n - i] % P) * c[i - 1] % P) % P;
}
}
printf("%lld\n", ans);
return 0;
}
标签:方案,Tokyo,Cup,int,题解,ll,删掉,Prix,操作
From: https://www.cnblogs.com/qjsswz/p/18392414