ABC 313
省流:ABC 没有什么好讲的,DEG 比较简单。
D
先求出
第一种是
E
连续两个
计算每一个
F
-
如果出现
,必须翻,如果 ,先翻过来再说,不会更劣。后面只考虑 。 -
如果对于一个
,有 或 , 翻转的概率是 ,否则为 。(可以用二项式定理证明) -
抽象成图,
到 连一条边。 -
每个点权是
,是选择它的“贡献”。 -
显然,连接两个点权是正的边,直接连接;连接两个点权是负的边,不可能连接。处理完,去掉这些边。
-
图变成了二分图。
, 很合理。 -
若负的点数量
,可以直接枚举,与它们连的正的边一定会选, ,预处理可以 。(最坏) -
反之,在正的上面 dp,
代表负的中选到了 ,正的选了 。 。
G
操作
Ex
-
给
和 排序没有影响。 -
定义
, 。 -
即可。
考虑插入 dp。
转移
-
单独成段。 -
在一段左或右边。 -
连接两段。
代码很好写。
code
#include <bits/stdc++.h>
using namespace std;
#define de(x) cout<<#x<<"="<<x<<endl
using ll = long long;
const int N = 5e3+3;
const ll mod = 998244353;
int n;
int a[N],b[N];
ll dp[N][N];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n;
for (int i=0; i<n; i++){
cin>>a[i];
}
for (int i=0; i<n+1; i++){
cin>>b[i];
}
sort(a,a+n);
sort(b,b+1+n);
dp[0][0]=1;
for (int i=0; i<n; i++){
for (int bl=0; bl<=i; bl++){
for (int ty=0; ty<3; ty++){
if (i+bl+1-ty>n || ty>bl){
continue;
}
if (ty!=2 && b[i+bl]<a[i]){
continue;
}
if (ty==0){
(dp[i+1][bl+1]+=dp[i][bl]*1ll*(bl+1)%mod)%=mod;
}
if (ty==1){
(dp[i+1][bl]+=dp[i][bl]*1ll*(2ll*bl)%mod)%=mod;
}
if (bl-1>=0 && ty==2){
(dp[i+1][bl-1]+=dp[i][bl]*1ll*(bl-1)%mod)%=mod;
}
}
}
}
cout<<dp[n][1]<<endl;
return 0;
}
// don't waste time!!!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?