题解 CF1750F 【Majority】
直接考虑合法条件似乎不太方便,考虑来观察一下一个长为
- 两端不全为
1 。 - 或操作到不能操作时每一个
0 连续段的长度皆> 其两边1 连续段的长度之和。
考虑 dp,设
初值:
转移:对于
对于其他
答案:
前缀和优化 dp 即可。具体地,维护一个
时间复杂度为
代码:
#include <stdio.h>
typedef long long ll;
int power[5007];
ll dp[5007][5007], sum1[10007], sum2[10007];
inline void init(int n, int m){
power[0] = 1;
for (int i = 1; i <= n; i++){
power[i] = power[i - 1] * 2 % m;
}
}
int main(){
int n, m, k;
scanf("%d %d", &n, &m);
init(n, m);
k = n * 2;
dp[1][1] = sum1[2] = 1;
for (int i = 2; i <= n; i++){
for (int j = 1; j <= k; j++){
sum2[j] = (sum2[j - 1] + sum1[j]) % m;
}
dp[i][i] = power[i - 2];
for (int j = 1; j * 2 < i; j++){
dp[i][j] = dp[j][j] * sum2[i - j * 2 - 1] % m;
dp[i][i] = ((dp[i][i] - dp[i][j]) % m + m) % m;
}
for (int j = 1; j <= i; j++){
int t = i + j;
sum1[t] = (sum1[t] + dp[i][j]) % m;
}
}
printf("%lld", dp[n][n]);
return 0;
}