标签:
“亚信科技杯”南邮第七届大学生程序设计竞赛之网络预赛
F
题目描述
教学楼有一台奇怪的自动售货机,它只售卖一种饮料,单价5元,并且只收5元、10元面值的货币,但是同学们都很喜欢喝。这个售货机里没有多余的找零,也就是说如果一个持有10元的同学第一个购买,则他不能获得5元找零,但是如果在他之前有一个持有5元的同学买了这种饮料,则他可以获得5元找零。
假设售货机的货源无限,每人只买一罐,现在有N个持有5元的同学和M个持有10元的同学想要购买,问一共有多少种排队方法可以让每个持有10元的同学都获得找零。(这里的排队方法以某一位置上人持的钱数来分,即只要同一位置上的同学所持钱的数目相同,就算同一种排队方法)
输入
多组测试数据
每组包含两个整数N,M(1<=M<=N<=1000),分别表示持有5元和10元的同学个数。
输出
输出一个整数,表示排队方法总数。由于结果可能很大,所以结果需要模1000000007。
样例输入
1 1
2 1
3 1
样例输出
1
2
3
题目来源
hjp
题解转自田神:
http://blog.csdn.net/tc_to_top/article/details/44745987
题目分析:这题其实很简单,开始想的太复杂了,开始当作卡特兰数 (Catalan数)做其实就是(C(n+m, m)%mod - C(n+m, m-1)%mod)%mod,数组递推组合数T了 ,用java写大数结果noj上mle,连乘组合数取余写跪了,下面说这题应该怎么做。
其实就是一个dp,dp[i][j]表示有i个人有5元,j个人有10元的排队方案数,我们可以发现:
dp[i][0] = 1,因为大家都只有5元,怎么排都是一种方案
i < j时dp[i][j] = 0,因为有5元的人比有10元的少,必然会出现找不开的情况,那么此时方案数就是0
不是以上两种情况时:dp[i][j]的方案数由dp[i - 1][j] + dp[i][j - 1]递推得到,考虑第m+n个人的状态
1.第m+n个人100,m+n-1里有m个50,n-1个100则dp[m][n-1]
2.第m+n个人50,m+n-1里有m-1个50,n个100则dp[m-1][n]
最后竟然忘了先预处理算一遍,- -
Accepted
|
937MS
|
16020K
|
887Byte
|
2015-03-30 20:03:08.0
|
1 #include <cstdio> 2 #include <cstring> 3 #include <stack> 4 #include <vector> 5 #include <queue> 6 #include <algorithm> 7 8 #define ll long long 9 int const N = 1005; 10 int const M = 205; 11 int const inf = 1000000000; 12 ll const mod = 1000000007; 13 14 using namespace std; 15 16 ll dp[2*N][N]; 17 int n,m; 18 19 void ini1() 20 { 21 memset(dp,0,sizeof(dp)); 22 dp[1][0]=1; 23 int i,j; 24 for(i=2;i<=2000;i++){ 25 for(j=0;j<=i/2;j++){ 26 dp[i][j]=(dp[i-1][j-1]+dp[i-1][j])%mod; 27 } 28 } 29 } 30 31 void ini() 32 { 33 34 } 35 36 void solve() 37 { 38 39 } 40 41 void out() 42 { 43 printf("%I64d\n",dp[n+m][m]); 44 } 45 46 int main() 47 { 48 ini1(); 49 //freopen("data.in","r",stdin); 50 // freopen("data.out","w",stdout); 51 //scanf("%d",&T); 52 //for(int cnt=1;cnt<=T;cnt++) 53 // while(T--) 54 while(scanf("%d%d",&n,&m)!=EOF) 55 { 56 ini(); 57 solve(); 58 out(); 59 } 60 }
“亚信科技杯”南邮第七届大学生程序设计竞赛之网络预赛 (部分题解)
标签:
原文地址:http://www.cnblogs.com/njczy2010/p/4379034.html