整数划分问题:
笼统上说就是将一根整数划分成若干个整数之和的方案数。整数划分很多不同的问法,也有隐晦的问法。比如n个苹果放到m个盘子里,比如n个砖块堆成m个层阶梯。关于整数划分,大概有以下这么多扩展的问题:
1,整数n划分成若干整数之和的方案数;
2,整数n划分成k个整数之和的方案数;
3,整数n划分成最大数不超过k的若干整数之和的方案数;
4,整数n划分成最小数不低于k的若干整数之和的方案数;
5,整数n划分成若干不同的整数之和的方案数;
6,整数n划分成k个不同整数之和的方案数;
7,整数n划分成最大数不超过k的若干不同整数之和的方案数;
8,整数n划分成最小数不低于k的若干不同整数之和的方案数;
9,整数n划分成若干奇数的方案数;
10,整数n划分成若干偶数的方案数;
这么多问题一个一个解决,其实解决其中一个问题,相关联的也迎刃而解。首先看第二个问题,为什么不看第一个问题呢?很简单仔细思考一下,枚举所有的k不就是第一个问题的解嘛。第二个问题的状态转移方程式 引入dp2[][]表示整数i分成j个整数的方案数
memset(dp2,0,sizeof(dp2));
dp2[0][0]=1;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=i;j++)
{
dp2[i][j]=dp2[i-1][j-1]+dp2[i-j][j];
}
}
怎么去解释这个状态转移方程呢?你可以把整数i分成j个整数之和看成i个苹果放到j个盘子里,不允许有空盘子。j个盘子,可以分成两种状态,所有盘子里最小的苹果数等于1,和大于1。等于1的情况,把这个最小苹果数的盘子拿掉,dp[i][j]=dp[i-1][j-1];若最小数大于1,那么把所有j的盘子都拿去一个苹果,dp[i][j]=dp[i-j][j]。那么第一个问题就也解决了。
现在看第三个问题,最大数不超过k的划分数
memset(dp3,0,sizeof(dp3));
dp3[0][0]=1;
for(int i=0;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i>=j)
dp3[i][j]