CF1608F MEX counting 口胡
显然,题目拆掉绝对值,题目变成了对于 的前缀的 有区间限制
考虑 DP ,设 表示前 位 , ,有 位数 的方案数
之所以这样设,是因为我们关心 ,并且不关心 的具体是那些数
容易列出方程:
注意,要先进行第一行的转移,因为第一行涉及到用 转移 ,否则会算错
最后的答案就是 ,那个排列数是为了得到 的 个数的实际方案
第一维显然可以滚掉,那么时间复杂度就是 ,空间
这道题卡常,蒟蒻被卡爆了,这里给出 @GreenSnake 的代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2000 + 5, K = 100 + 5, Mod = 998244353;
int n = 0, k = 0, b[N] = {}, m = 0, p = 0;
int dp[2][K][N] = {}, g[N] = {}, ans = 0;
int main(){
scanf("%d %d", &n, &k);
for(int i = 1 ; i <= n ; ++ i) scanf("%d", &b[i]);
dp[0][k][0] = 1;
for(int i = 1 ; i <= n ; ++ i){
p = p ^ 1;
for(int j = 0 ; j <= i + 1 ; ++ j) g[j] = 0;
for(int mex = m ; mex <= min(b[i] + k, i) ; ++ mex) for(int j = 0 ; j <= i - mex ; ++ j){
g[j] = 1ll * g[j + 1] * (j + 1) % Mod;
if(mex > m && mex - 1 <= b[i - 1] + k) g[j] = (g[j] + dp[p ^ 1][mex - 1 - b[i - 1] + k][j]) % Mod;
if(mex >= b[i] - k){
dp[p][mex - b[i] + k][j] = g[j];
if(mex <= b[i - 1] + k && mex < i){
if(j + mex < i) dp[p][mex - b[i] + k][j] = (dp[p][mex - b[i] + k][j] + 1ll * dp[p ^ 1][mex - b[i - 1] + k][j] * (j + mex)) % Mod;
if(j && j + mex - 1 < i) dp[p][mex - b[i] + k][j] = (dp[p][mex - b[i] + k][j] + dp[p ^ 1][mex - b[i - 1] + k][j - 1]) % Mod;
}
}
}
m = max(m, b[i] - k);
}
for(int j = 0 ; j <= n ; ++ j) g[j] = 0;
for(int mex = m ; mex <= n ; ++ mex) for(int j = 0 ; j <= n - mex ; ++ j){
if(mex <= b[n] + k) g[j] = (g[j] + dp[p][mex - b[n] + k][j]) % Mod;
if(j) g[j - 1] = 1ll * g[j] * (n - mex) % Mod;
else ans = (ans + g[j]) % Mod;
}
printf("%d", ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通