原始题目
放苹果
- Time Limit: 1000MS
- Memory Limit: 10000K
- Total Submissions: 37069
- Accepted: 22825
Description
把 M 个同样的苹果放在 N 个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用 K 表示)5,1,1 和 1,5,1 是同一种分法。
第一行是测试数据的数目$ t(0 t 20)$。以下每行均包含二个整数 M 和 N,以空格分开。 $ 1 M , N 10 $。
Output
对输入的每组数据 M 和 N,用一行输出相应的 K。
1
7 3
Sample Output
8
Source
lwx@POJ
题目大意
如题
解题思路
- \(dp[i][j]\) 表示 i 个苹果 j 个盘子的分法。
- 状态转移: - 当\(i<j\)时,\(dp[i][j]=dp[i][i]\) (不区分盘子,所以盘子多余的情况数和盘子恰好和苹果数相等的情况数相等) - 当\(i\geqslantj\),\(dp[i][j]=dp[i-j][j]+dp[i][j-1]\) (每个盘子都有苹果和有一个盘子没有苹果两种状况转移) 注意初始的情况就好。
解题代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| #include <cstdio> #include <cstring> #include <iostream> #include <set> #include <algorithm> #include <queue> #include <map> #include <string> #define eps 1e-8 #define INF 0x3f3f3f3f #define rep(i,a,n) for(int i=a;i<n;i++) #define per(i,a,n) for(int i=n-1;i>=a;i--) using namespace std; const int maxn=1e8+2; typedef long long ll;
ll dp[22][22]; void solve(){ memset(dp,0,sizeof(dp)); dp[0][0]=1; for(int i=0;i<=21;i++){ for(int j=0;j<=21;j++){ if(i==0) dp[i][j]=1; else if(j==0) dp[i][j]=0; else if(j==1) dp[i][j]=1; else { if(i<j) dp[i][j]=dp[i][i]; else dp[i][j]=dp[i][j-1]+dp[i-j][j];
} } } }
int main(){ int t; solve(); while(cin>>t){ int m,n; rep(i,0,t){ cin>>m>>n; cout<<dp[m][n]<<endl; } } }
|
收获与反思
注意边界情况的考量