codeforces—Caesar's Legions补11.16training

Problem - F - Codeforces

Gaius Julius Caesar, a famous general, loved to line up his soldiers. Overall the army had n1 footmen and n2 horsemen. Caesar thought that an arrangement is not beautiful if somewhere in the line there are strictly more that k1 footmen standing successively one after another, or there are strictly more than k2 horsemen standing successively one after another. Find the number of beautiful arrangements of the soldiers.

Note that all n1 + n2 warriors should be present at each arrangement. All footmen are considered indistinguishable among themselves. Similarly, all horsemen are considered indistinguishable among themselves.

Input

The only line contains four space-separated integers n1, n2, k1, k2 (1 ≤ n1, n2 ≤ 100, 1 ≤ k1, k2 ≤ 10) which represent how many footmen and horsemen there are and the largest acceptable number of footmen and horsemen standing in succession, correspondingly.

输入

唯一一行包含四个空格分隔的整数 n1n2k1k2 ( 1 ≤ n1, n2 ≤ 100, 1 ≤ k1, k2 ≤ 10 ),分别表示有多少名步兵和骑兵,以及最大可接受的步兵和骑兵人数。

Output

Print the number of beautiful arrangements of the army modulo 100000000 (108). That is, print the number of such ways to line up the soldiers, that no more than k1 footmen stand successively, and no more than k2 horsemen stand successively.

输出

打印军队的漂亮排列模数 100000000 (108) 。 (108) .也就是说,打印这样的排兵布阵方式的数量,即连续站立的步兵不超过 k1 个,连续站立的骑兵不超过 k2 个。


Examples

Input

2 1 1 10

Output

1

Input

2 3 1 2

Output

5

Input

2 4 1 1

Output

0

Note

Let's mark a footman as 1, and a horseman as 2.

In the first sample the only beautiful line-up is: 121

In the second sample 5 beautiful line-ups exist: 12122, 12212, 21212, 21221, 22121

注意

让我们把脚夫标记为1,把骑士标记为2。

在第一个样本中,唯一漂亮的阵容是121。

在第二个示例中,有 5 个漂亮阵容:12122, 12212, 21212, 21221, 22121


题解

最一开始我用的dfs去做

查看代码
  
 
#include
using namespace std;
int ans = 0;
int a,b,n,m;
void dfs(int res,bool flag,int a_r,int b_r){
    if(res == 0)
        ans++;
    if(flag == 1){
        if(b_r <= 0)return;
        for(int i = 1;i <= m;i++)
        if(i <= b_r)
            dfs(res-i,0,a_r,b_r-i);
    }
    if(flag == 0){
        if(a_r <= 0)return;
        for(int i = 1;i <= n;i++)
        if(i <= a_r)
            dfs(res-i,1,a_r-i,b_r);
}
}
int main() {

cin>>a>>b>>n>>m;
dfs(a+b,1,a,b);
dfs(a+b,0,a,b);
cout<<ans<<endl;
return 0;
}
 

先不考虑取模,首先这个代码直接tle掉了,递归的次数太多了

接下来介绍正确做法计数dp
代码如下

#include<bits/stdc++.h>
using namespace std;
long long ans = 0;
int a,b,n,m;
int dp[205][105][2];//dp[x][y][z]表示前x个士兵,有y个骑兵,并且以z为最后一个的方案数,这里我们用z == 1去代表骑兵,以z == 0去代表步兵
int mod = 1e8;
int main() {
 
    cin>>a>>b>>n>>m;
    dp[0][0][1] = dp[0][0][0] = 1;
    for(int i = 1;i <= a+b;i++){//首先从头到尾去遍历整排
        for(int j = 0;j <= b;j++){//前i个士兵,有j个骑兵
            for(int k = i- 1;k >=max(0,i-n);k--)
            //如果要计算前i个士兵,有j个骑兵,并且以步兵为最后一个的方案数,
            //那么我们可以等于前k个士兵,有j个骑兵,并且以骑兵为最后一个的方案数求和
            //因为我们可以在其后面添加不超过n个步兵,这样就是dp[i][j][0]
                dp[i][j][0] = (dp[i][j][0] + dp[k][j][1])%mod;
            for(int k = i-1;k >=max(i-m,max(0,i-j));k--)//同理
                dp[i][j][1] = (dp[i][j][1]+dp[k][j-(i-k)][0])%mod;
        }
    }
    cout<<(dp[a+b][b][0]+dp[a+b][b][1])%mod<<endl;
    return 0;
}
posted @ 2023-12-06 22:43  LongDz  阅读(16)  评论(0)    收藏  举报