整数划分(二)
时间限制:
1000 ms | 内存限制:
65535 KB
难度:
3
-
描述
-
把一个正整数m分成n个正整数的和,有多少种分法?
例:把5分成3个正正数的和,有两种分法:
1 1 3
1 2 2
-
输入
-
第一行是一个整数T表示共有T组测试数据(T<=50)
每组测试数据都是两个正整数m,n,其中(1<=n<=m<=100),分别表示要拆分的正数和拆分的正整数的个数。
输出
-
输出拆分的方法的数目。
样例输入
-
2 5 2 5 3
样例输出
-
2 2
来源
这个题是对m划分为n个数,注意与90题的区别,但是思路差不多:
设dp[m][n],为题义要求
当n==m时,这个时候只有一种划分方法及n个一;
当n>m时,这个时候划分数为0,因为当划分的数全为1时为最多的划分个数(此时m=n),所以n不能大于m
当n<m时,这个时候可以这样看:
设所有划分出的数都大于1,即最小的划分数为2,这种情况可以看作先把n个数设为1,然后再从剩下的m-n个数中划分为n个数即dp[m-n][n]
若这n个划分数中肯定含有一个1,则相当于对m-1进行n-1个数的划分即dp[m-1][n-1]
所以dp[m][n]=dp[m-n][n]+dp[m-1][n-1];
#include<iostream> #define MAX 105 using namespace std; int dp[MAX][MAX]; int main(){ int T; cin>>T; for(int i=1;i<MAX;i++){ dp[i][1]=dp[1][i]=1; } for(int i=1;i<MAX;i++){ for(int j=1;j<MAX;j++){ if(i==j){ dp[i][j]=1; } else if(i<j){ dp[i][j]=0; } else if(i>j){ dp[i][j]=dp[i-j][j]+dp[i-1][j-1]; } } } while(T--){ int m,n; cin>>m>>n; cout<<dp[m][n]<<endl; } }
-
第一行是一个整数T表示共有T组测试数据(T<=50)