当前位置: 首页 > backend >正文

【codeforces 2086d】背包+组合数学

【codeforces 2086d】背包+组合数学

Problem - D - Codeforces
题意:
给出字符串中每个字符的出现次数 c i ( 1 ≤ i ≤ 26 ) c_i(1 \leq i \leq 26) ci(1i26)。现构造一个字符串,要求任意相同字母之间的距离必须是偶数。求满足要求的字符串的数量。

其中, ∑ c i ≤ 5 × 1 0 5 \sum c_i \leq 5 \times 10^5 ci5×105

例如, c [ 27 ] = 2 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 c[27] = {2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} c[27]=2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,可以构造出的字符串有 4 4 4个: a b a k abak abak a k a b akab akab b a k a baka baka k a b a kaba kaba


思路:
我们发现对于一个字母来说,我们必须将其全部放在奇数位或者全部放在偶数位,才能保证任意相同字母之间的距离必须是偶数。

也就是说,对于字母 x x x来说,我们有两种决策方式:将其全部放入奇数位;将其全部放入偶数位。

同时,我们发现位数是有限的。考虑(背包)动态规划。

首先计算出奇数有 L L L位,偶数有 R R R位。令 f [ i ] [ j ] f[i][j] f[i][j]表示考虑第 i i i个字符,决策完后,奇数位放了 j j j个字母。

  • 第一种决策:放偶数位

    f [ i ] [ j ] = f [ i ] [ j ] + ( s [ i ] − j ≤ R a n d s [ i − 1 ] ≥ j ) × f [ i − 1 ] [ j ] × C R − ( s [ i − 1 ] − j ) c [ i ] f[i][j] = f[i][j] + (s[i] - j \leq R \ \ and\ \ s[i - 1] \geq j) \times f[i - 1][j] \times C_{R - (s[i - 1] - j)}^{c[i]} f[i][j]=f[i][j]+(s[i]jR  and  s[i1]j)×f[i1][j]×CR(s[i1]j)c[i] 其中 s [ i ] = ∑ k = 1 i c k s[i] = \sum_{k = 1}^{i}c_k s[i]=k=1ick

  • 第二种决策:放奇数位

    f [ i ] [ j ] = f [ i ] [ j ] + ( j − c [ i ] ≤ L a n d j ≥ c [ i ] ) × f [ i − 1 ] [ j − c [ i ] ] × C L − ( j − c [ i ] ) c [ i ] f[i][j] = f[i][j] + (j - c[i] \leq L \ \ and \ \ j \geq c[i]) \times f[i - 1][j - c[i]] \times C_{L - (j - c[i])}^{c[i]} f[i][j]=f[i][j]+(jc[i]L  and  jc[i])×f[i1][jc[i]]×CL(jc[i])c[i]

C C C表示组合数,预处理组合数可用 C n m = n ! m ! ( n − m ) ! = f a c t [ n ] × i n f a c t [ m ] × i n f a c t [ n − m ] C_n^m = \frac{n!}{m!(n - m)!} = fact[n] \times infact[m] \times infact[n - m] Cnm=m!(nm)!n!=fact[n]×infact[m]×infact[nm]


我认为动态规划问题通常考虑在问题规模缩小和扩大时,变量是什么。

例如此题,在构造字符串这个问题规模不断缩小和扩大时,奇数位的数量在变化。同时,我们考虑的字母也是不同的。我们不妨将此都加入状态中思考怎么转移。此外,我们还可以基于熟悉的背包模型,思考此题的状态。在方案数的计算上,我们更容易体会到 d p dp dp数组记录一类方案,直接查表的过程。

在观察一道题是否是动态规划时,或转移方程是什么时,我通常思考有哪些决策。例如此题,我们经过推理,得到决策后,动态规划的转移方程也呼之欲出。在 a c w i n g acwing acwing的动态规划讲解中,如何决策也等同于如何划分集合。


代码如下:

#include <bits/stdc++.h>
using namespace std;
using LL = long long;
#define endl "\n"const int n = 26, N = 30, M = 5e5 + 10, mod = 998244353;
LL c[N], s[N];
LL fact[M], infact[M];
LL f[N][M];LL qmi(LL a, LL b) {LL res = 1;while (b) {if (b & 1) res = res * a % mod;a = a * a % mod;b >>= 1;}return res;
}LL inv(LL a) {return qmi(a, mod - 2);
}LL comb(LL a, LL b) {return fact[a] % mod * infact[b] % mod * infact[a - b] % mod;
}void init(int n) {fact[0] = 1;for (int i = 1; i <= n; i ++) fact[i] = fact[i - 1] * i % mod;infact[n] = inv(fact[n]);for (int i = n - 1; i >= 0; i --) infact[i] = infact[i + 1] * (i + 1) % mod;
}void solve() {for (int i = 1; i <= n; i ++) cin >> c[i];memset(s, 0, sizeof s);for (int i = 1; i <= n; i ++) s[i] = s[i - 1] + c[i];LL L = 0, R = 0;if (s[n] & 1) {L = s[n] / 2 + 1, R = s[n] - L;} else {L = s[n] / 2, R = s[n] / 2;}for (int i = 1; i <= n; i ++) {for (int j = 0; j <= s[i]; j ++) {f[i][j] = 0;}}f[0][0] = 1;for (int i = 1; i <= n; i ++) {if (!c[i]) {for (int j = 0; j <= min(s[i], L); j ++) {f[i][j] = f[i - 1][j];}continue;}for (int j = 0; j <= min(s[i], L); j ++) {if (s[i] - j <= R && s[i - 1] >= j) {f[i][j] += f[i - 1][j] * comb(R - s[i - 1] + j, c[i]) % mod;f[i][j] %= mod;}if (j >= c[i] && L - j + c[i] >= 0) {f[i][j] += f[i - 1][j - c[i]] * comb(L - j + c[i], c[i]) % mod;f[i][j] %= mod;}}}cout << f[n][L] << endl;
}int main() {ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);init(M - 1);int t; cin >> t;while (t --) solve();return 0;
}
http://www.xdnf.cn/news/3120.html

相关文章:

  • Java之BigDecimal
  • 杭电oj(1015、1016、1072、1075)题解
  • 在线文章系统自动化测试报告
  • MIT6.S081-lab7前置
  • 免费超好用的电脑操控局域网内的手机(多台,无线)
  • Leetcode 3530. Maximum Profit from Valid Topological Order in DAG
  • CSS:编写位置分类及优先级
  • 从Markdown到专业文档:如何用Python打造高效格式转换工具
  • Qwen3-8B安装与体验-速度很快!
  • Yaml文件
  • 数字逻辑--期末大复习
  • 激光雷达点云去畸变
  • ctf.show 卷王杯 pwn签到
  • DDI0487--A1.7
  • onlyoffice部署
  • Ignoring query to other database
  • Elasticsearch:ES|QL lookup JOIN 介绍 - 8.18/9.0
  • STP学习
  • 排序版研究方向
  • docker部署的Nextcloud,处于维护模式,如何解决
  • 华为自研的仓颉编程语言介绍
  • Qwen3 系列的后训练技术
  • 无人机航拍羊只检测数据集VOC+YOLO格式6065张1类别
  • Spring计时器StopWatch 统计各个方法执行时间和占比
  • ModbusRTU转PROFIBUS网关通讯
  • 30天通过软考高项-第七天
  • 如何计算数码显微镜的放大倍率
  • Kubernetes集群使用Harbor容器镜像仓库
  • 【数据治理】数据生命周期
  • ESP32- 开发笔记- 软件开发 4 - GPIO 口