2019牛客暑期多校训练营第一场 E ABBA

 注意:

有的时候memset会出问题

思路:

i代表A,j代表B,题目要求n个AB,m个BA,所以在一个字符串中,前n个A贡献给AB中的A,前m个B贡献给BA中的B,这里用到贪心的思想

所以当i<=n时,直接用于贡献给AB中的A,当i>n时,i-n个A用来组成BA,因此当j>i-n时,此时可以放A组成BA,例如当j=3,i-n=2时,可以再放一个A组成3个BA,dp[i+1][j]=dp[i+1][j]+dp[i][j];同理,当i>j-m时,可以放B组成BA;最后不要忘了%mod.

 

代码:

#include<iostream>
using namespace std;
const int maxn = 2005;
const int mod = 1e9+7;
int dp[maxn][maxn];
int main(){
    int n,m;
    while(cin>>n>>m){
        for(int i=0;i<=n+m;i++)
            for(int j=0;j<=n+m;j++)
                dp[i][j]=0;
        dp[0][0]=1;
        for(int i=0;i<=n+m;i++){
            for(int j=0;j<=n+m;j++){
                if(j+n>i)
                    dp[i+1][j] = (dp[i+1][j]+dp[i][j])%mod;
                if(i+m>j)
                    dp[i][j+1] = (dp[i][j+1]+dp[i][j])%mod;                    
            }
        }
        cout<<dp[n+m][n+m]<<endl;
    }
    return 0;
} 

 方法二:

 

我们要从(0,0)点出发到达(n+m,n+m)并在要求的运动区域内的运动路径不同的个数;

两条直线:y>x-n     x>y-m;所围成的粉红色区域就是可以运动的区域

y=x-(n+1)所代表的绿色直线就是y=x-n向右移动一格的直线,只要经过这条直线那么就代表不符合要求中的一种情况,另一种情况:y=x+(m+1),所以我们用c[2*(n+m)][n+m]-符合要求的就是答案

不符合要求的(m-1)+(n+m)+(n-1)中取(m-1)+c[2*(n+m)][n-1];

 

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
const int maxn = 4e3+5;
typedef long long ll;
ll a[maxn][maxn];
int main(){
    int n,m;
    a[0][0]=1;
    for(int i=1;i<=4004;i++){//一旦大于等于4005就会段错误
        a[i][0] = 1;a[i][i] =1;
        for(int j=1;j<i;j++){
            a[i][j] = (a[i-1][j-1]+a[i-1][j])%mod;
        }
    }
    while(cin>>n>>m){
        cout<<(a[2*(n+m)][n+m]-(a[2*(n+m)][m-1]+a[2*(n+m)][n-1])%mod+mod)%mod<<endl;
    }
    return 0;
}

 

posted @ 2020-02-23 23:34  sqsq  阅读(105)  评论(0编辑  收藏  举报