组合数前缀和以及相关恒等式
https://blog.csdn.net/caoyang1123/article/details/119682449
https://blog.nowcoder.net/n/81842ed1c5a14330902d3ef9a7403c6f
const int N = 5007;
const int mod = 1e9 + 7;
int fac[N * 2] = {1, 1}, inv[N * 2] = {1, 1};
inline void init() {
for (int i = 2; i < N * 2; ++i) {
fac[i] = (ll)fac[i - 1] * i % mod;
inv[i] = (ll)(mod - mod / i) % mod * inv[mod % i] % mod;
}
for (int i = 1; i < N * 2; ++i) inv[i] = (ll)inv[i] * inv[i - 1] % mod;
}
inline int C(int n, int m) {
if (n < m) return 0;
if (n == m) return 1;
return (ll)fac[n] * inv[m] % mod * inv[n - m] % mod;
}
ll C(ll n, ll m) {//组合数 C(n,m)
if (m < 0) return 0;
if (n < m) return 0;
if (m > n - m) m = n - m;
ll up = 1, down = 1;
for (ll i = 0; i < m; i++) {
up = up * (n - i) % mod;
down = down * (i + 1) % mod;
}
return up * getInv(down) % mod;
} Double Strings
用dp转移相同子序列数量,用组合数计算两串选出等长串,能选多少种
#include <bits/stdc++.h>
#define sc(x) scanf("%lld", &(x))
#define pr(x) printf("%lld\n", (x))
#define rep(i, l, r) for (int i = l; i <= r; ++i)
using namespace std;
typedef long long ll;
const int N = 5007;
const int mod = 1e9 + 7;
int fac[N * 2] = {1, 1}, inv[N * 2] = {1, 1};
int dp[N][N]; // dp[i][j]表示 在A串前i个字符 B串前j个字符 有多少子序列相同
char a[N], b[N];
inline void init() {
for (int i = 2; i < N * 2; ++i) {
fac[i] = (ll)fac[i - 1] * i % mod;
inv[i] = (ll)(mod - mod / i) % mod * inv[mod % i] % mod;
}
for (int i = 1; i < N * 2; ++i) inv[i] = (ll)inv[i] * inv[i - 1] % mod;
}
inline int C(int n, int m) {
if (n < m) return 0;
if (n == m) return 1;
return (ll)fac[n] * inv[m] % mod * inv[n - m] % mod;
}
signed main() {
init();
scanf("%s%s", a + 1, b + 1);
int n = strlen(a + 1), m = strlen(b + 1);
rep(i, 1, n) rep(j, 1, m) {
dp[i][j] = (dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1]) % mod;
// 考虑不在两串中同时加入本字符的情况,那么就要么从a串尾缀,要么从b串尾缀,容斥处理一下即可
if (a[i] == b[j]) dp[i][j] = (dp[i][j] + dp[i - 1][j - 1] + 1) % mod;
// 如果a[i] == b[j] 即考虑同时在两串中加入本字符的情况
// dp[i][j]可以自dp[i-1][j-1]转移(即尾缀本字符)
// 也可以重新开始(+1) 即从本位开始
if (dp[i][j] < 0) dp[i][j] += mod;
}
ll ans = 0;
rep(i, 1, n) rep(j, 1, m)
if (b[j] > a[i])
// 前面相同(加一个空串),后面随便选
ans = (ans + (ll)(dp[i - 1][j - 1] + 1) * C(n - i + m - j, n - i)) % mod;
pr(ans);
return 0;
} 算法竞赛之路 文章被收录于专栏
整理、记录算法竞赛的好题
美的集团公司福利 819人发布

