您的位置:首页 > 文旅 > 美景 > 成都最正规的装修公司_手机pc端浏览器_河南省网站_网站怎么做外链

成都最正规的装修公司_手机pc端浏览器_河南省网站_网站怎么做外链

2025/7/13 10:02:39 来源:https://blog.csdn.net/Doctor_Anonymous/article/details/147616088  浏览:    关键词:成都最正规的装修公司_手机pc端浏览器_河南省网站_网站怎么做外链
成都最正规的装修公司_手机pc端浏览器_河南省网站_网站怎么做外链

【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;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com