集训队的晚饭 | ||||||
| ||||||
Description | ||||||
集训队的晚饭经常是去校外吃盖饭的,一份10元,饭后结账。 结账时,同学们要排队按顺序结账,有n人拿的是20元,m人拿的是10元。但这时发现老板娘没有准备任何零钱,她只能靠收取同学们交的10元钱来找同学们交的20元,而且每个交20元的同学都要求立即找钱。 老板娘想知道到底有多少种不同的收钱顺序。(收相同的面值,不同的人被认为是一样的。例如第一个收A的10元或者B的10元是一样的。) | ||||||
Input | ||||||
输入包含多组测试数据。 对于每组测试数据: 第1行,包含两个正整数m, n (1 ≤ m, n ≤ 1000) 分别代表这拿10元钱的人数和拿20元的人数。 处理到文件结束 | ||||||
Output | ||||||
对于每组测试数据: 第1行,输出老板娘有多少种不同的收钱顺序。(MOD 1000000007) | ||||||
Sample Input | ||||||
3 1 | ||||||
Sample Output | ||||||
3 | ||||||
Author | ||||||
齐达拉图@HRBUST |
我们设dp【i】【j】表示当前拿十块钱的人数为i,拿二十块钱的人数为j的方案数。
辣么我们推出状态转移方程:
dp【i】【j】(i>=j)=dp【i-1】【j】+dp【i】【j-1】只要当前的状态是i>=j,那么就有方案数,并且当前拿10块钱的i个人和拿20块钱的j个人是可以从状态为:i-1个拿十块钱的人和j个拿20块钱的人再来一个拿十块钱的人的状态转移过来的。同理,当前拿10块钱的i个人和拿20块钱的j个人是也可以从状态为:i个拿十块钱的人和j-1个拿20块钱的人再来一个拿20块钱的人的状态转移过来的。
注意事项:别忘记mod操作;
AC代码:
#include<stdio.h>
#include<string.h>
using namespace std;
int dp[1005][1005];
void init()
{
for(int i=0;i<1005;i++)
{
dp[i][0]=1;//全是十块钱的只有一种方案。
}
for(int i=1;i<=1004;i++)
{
for(int j=1;j<=i;j++)//只要i大于等于j,都是有可行方案。
{
dp[i][j]=(dp[i-1][j]+dp[i][j-1])%1000000007;//来一个拿十块钱的和来一个拿20块钱的都有可行方案。
}
}
}
int main()
{
init();
int n,m;
while(~scanf("%d%d",&n,&m))
{
printf("%d\n",dp[n][m]);
}
}