As(这个神秘的男人)给我随机分到的题
题意:
给出n1个1,n2个2,给出k1和k2代表连续的1和2的最大长度,问能够构造的合法的不同串的数量。
一开题看数据范围就知道不用优化,于是直接给Cy神仙说是红题(LuoGu紫题肯定是被恶意评分了),于是又被Zxh大神仙嘲讽了
真的不难,计数Dp,方程易推
f
[
a
]
[
b
]
[
c
]
[
d
]
f[a][b][c][d]
f[a][b][c][d]表示对于前a个士兵,第a个是兵种(0为步兵,1为骑兵),末尾有连续c个该兵种,总共有d个该兵种
然后可知如果第a个兵种的方案可以由第a-1个兵种相同且满足规则(总数不超过且连续数不超过)或第a-1个兵种不同的方案数相加得到
于是就很好推了
初始化
f
[
1
]
[
0
]
[
1
]
[
1
]
=
f
[
1
]
[
1
]
[
1
]
[
1
]
=
1
f[1][0][1][1]=f[1][1][1][1]=1
f[1][0][1][1]=f[1][1][1][1]=1
然后从2开始做
(由于本来看的是题目大意,然后不知道要取模而错了两次的弱智Code_Note)
附上代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define ll long long
#define MAXN 210
#define MOD 100000000
int n, m, a, b;
ll ans;
ll f[MAXN][2][MAXN][MAXN];
inline int read() {
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (s == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
int main() {
n = read(), m = read();
a = read(), b = read();
f[1][0][1][1] = 1;
f[1][1][1][1] = 1;
for (register int i = 2; i <= n + m; i++) {
for (register int j = 2; j <= a; j++)
for (register int k = 1; k <= n; k++)
(f[i][0][j][k] += f[i - 1][0][j - 1][k - 1]) %= MOD;
for (register int j = 2; j <= b; j++)
for (register int k = 1; k <= m; k++)
(f[i][1][j][k] += f[i - 1][1][j - 1][k - 1]) %= MOD;
for (register int j = 1; j <= a; j++)
for (register int k = 1; k <= n; k++)
if (i - k >= 0)
(f[i][1][1][i - k] += f[i - 1][0][j][k]) %= MOD;
for (register int j = 1; j <= b; j++)
for (register int k = 1; k <= m; k++)
if (i - k >= 0)
(f[i][0][1][i - k] += f[i - 1][1][j][k]) %= MOD;
}
for (register int i = 1; i <= a; i++)
(ans += f[n + m][0][i][n]) %= MOD;;
for (register int i = 1; i <= b; i++)
(ans += f[n + m][1][i][m]) %= MOD;;
printf("%lld", ans);
return 0;
}
这是我写的最认真的一次题解了!