CF756D Bacterial Melee[dp,组合数]
Posted isaunoya
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF756D Bacterial Melee[dp,组合数]相关的知识,希望对你有一定的参考价值。
首先定义一个状态 (dp_{j,c}) 表示选了 (j) 个位置最后一个字符是 (c)。
转移方程是
(dp_{j,c} = sum dp_{j-1,k} [k
eq c])
代表的是长度为 (j) 的以 (c) 结尾的方案数…
然后你发现,这个其实可以把 abc 变成 aab 的,所以很显然…是跟断点数量有关,假设你有 (m) 个断点,你发现你选的这个其实是个组合数 ((^n_m)) 其实证明就是当做断点来看,然后每次你枚举长度,倒序枚举,大概是01背包的那种想法,把不相同的全部加进来…这样就做完了。
// by Isaunoya
#include<bits/stdc++.h>
using namespace std;
struct io {
char buf[1 << 23 | 3], *s; int f;
io() { f = 0, buf[fread(s = buf, 1, 1 << 23, stdin)] = ‘
‘; }
io& operator >> (int&x) {
for(x = f = 0; !isdigit(*s); ++s) f |= *s == ‘-‘;
while(isdigit(*s)) x = x * 10 + (*s++ ^ 48);
return x = f ? -x : x, *this;
}
};
const int maxn = 5e3 + 35;
const int mod = 1e9 + 7;
int C[maxn][maxn];
int dp[maxn][27];
int add(int x, int y) {
return (x + y >= mod) ? (x + y - mod) : (x + y);
}
signed main() {
string s;
vector<int> a;
ios :: sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int len; cin >> len; cin >> s;
a.clear(); a.push_back(0);
for(char x: s) {
int c = x - ‘a‘ + 1;
if(c == a.back()) continue;
a.push_back(c);
}
int n = len;
C[0][0] = 1;
for(int i = 1 ; i <= n ; i ++) {
for(int j = 1 ; j <= i ; j ++) { C[i][j] = add(C[i - 1][j], C[i - 1][j - 1]); }
}
dp[0][0] = 1;
for(int i = 1 ; i < a.size() ; i ++) {
for(int j = i ; j ; j --) {
int x = a[i], ans = 0;
for(int c = 0; c <= 26; c ++) { if(c ^ x) { ans = add(ans, dp[j - 1][c]); } }
dp[j][x] = ans;
}
}
int ans = 0;
for(int i = 1 ; i < a.size(); i ++) {
int tmp = 0;
for(int c = 1 ; c <= 26 ; c ++) tmp = add(tmp, dp[i][c]);
ans = add(ans, 1ll * C[n][i] * tmp % mod);
}
cout << ans << ‘
‘;
return 0;
}
以上是关于CF756D Bacterial Melee[dp,组合数]的主要内容,如果未能解决你的问题,请参考以下文章
Fast and accurate bacterial species identification in urine specimens using LC-MS/MS mass spectromet
从Random Walk谈到Bacterial foraging optimization algorithm(BFOA),再谈到Ramdom Walk Graph Segmentation图分割算法