dp整数划分问题——03:复杂的整数划分问题

来源:互联网 发布:淘宝首页轮播图多大 编辑:程序博客网 时间:2024/06/06 10:47

整数划分 :
  这道好题求:
  1. 将n划分成若干正整数之和的划分数。
  2. 将n划分成k个正整数之和的划分数。
  3. 将n划分成最大数不超过k的划分数。
  4. 将n划分成若干奇正整数之和的划分数。
  5. 将n划分成若干不同整数之和的划分数。

 

1.若划分的多个整数可以相同

  设dp[i][j]为将i划分为不大于j的划分数

  (1) 当i<j时,i不能划分为大于i的数,所以dp[i][j]=dp[i][i]

  (2) 当i>j时,可以根据划分中是否含有j分为两种情况。

                                    若划分中含有j,划分方案数为dp[i-j][j]

                                    若划分数中不含j,相当于将i划分为不大于j-1的划分数,为dp[i][j-1]

                            所以当i>jdp[i][j]=dp[i-j][j]+dp[i][j-1]

  (3) 当i=j时,也分为两种情况:

                                     若划分中含有j只有一种情况,

                                     若划分中不含j相当于将i划分为不大于j-1的划分数。

                           此时dp[i][j]=1+dp[i][j-1]。


2.若划分的正整数必须不同

  设dp[i][j]为将i划分为不超过j的不同整数的划分数

  (1) 当i<j时,i不能划分为大于i的数,所以dp[i][j]=dp[i][i]

  (2) 当i>j时,可以根据划分中是否含有j分为两种情况。

                                   若划分中含有j,则其余的划分中最大只能是j-1,方案数为dp[i-j][j-1]

                                   若划分中不含j,相当于将i划分为不大于j-1的划分数,为dp[i][j-1]

                            所以当i>jdp[i][j]=dp[i-j][j-1]+dp[i][j-1]

  (3) 当i=j时,两种情况:

                                   若划分中含有j只有一种情况;

                                   若划分中不含j相当于将i划分为不大于j-1的划分数。

                           此时dp[i][j]=1+dp[i][j-1]。


 

二 将n划分为k个整数的划分数

dp[i][j]为将i划分为j个整数的划分数。

  (1) i<j为不可能出现的情况,dp[i][j]=0

  (2) 若i=j,有一种情况:i可以划分为i1之和,dp[i][j]=1

  (3) 若i>j,可以根据划分数中是否含有1分为两类:

                               若划分数中含有1,可以使用“截边法”将j个划分分别截去一个1

                                               把问题转化为i-jj-1个划分数,为dp[i-j][j-1]; 

                               若划分中不包含1,使用“截边法”将j个划分数的最下面一个数截去,

                                               将为题转化为求i-jj个划分数,为dp[i-j][j]。所以i>jdp[i][j]=dp[i-j][j-1]+dp[i-j][j]。



 

三 将n划分为若干正奇数之和的划分数

 

f[i][j]为将i划分为j个奇数之和的划分数,g[i][j]为将i划分为j个偶数之和的划分数。

使用截边法,将g[i][j]j个划分都去掉1,可以得到f[i-j][j],所以

g[i][j] = f[i-j][j]

f[i][j]中有包含1的划分方案和不包含1的划分方案。对于包含1的划分方案,可以将1的划分除去,转化为“将i-1划分为j-1个奇数之和的划分数”,即f[i-1][j-1];对于不包含1的划分方案,可以使用截边法对j个划分每一个都去掉一个1,转化为“将i-j划分为j个偶数之和的划分数”,即g[i-j][j]

所以f[i][j]=f[i-1][j-1]+g[i-j][j]

f[n][0]+f[n][1]+……+f[n][n]为将n划分为若干奇数的划分数,为问题4的答案。



另:

将整数划分成连续正整数之和:


如15可以划分成4种连续整数相加的形式:
15
7 8
4 5 6
1 2 3 4 5

    首先考虑一般的形式,设n为被划分的正整数,x为划分后最小的整数,如果n有一种划分,那么
结果就是x,如果有两种划分,就是x和x 、x + 1, 如果有i种划分,就是

x ;

x 、x + 1 ;

x、 x + 1、 x + 2 、... ;

x、 x + 1、 x + 2、 ... 、 x + i - 1;
将每一个结果相加得到一个公式(i * x + i * (i - 1) / 2) = n,i为当前划分后相加的正整数个数。
满足条件的划分就是使x为正整数的所有情况。
如上例,

当i = 1时,x = 15;

当i = 2时, x = 7;

当i = 3时,x = 4;

当i = 4时,x = 4/9;      (x不是正整数,因此,15不可能划分成4个正整数相加)

当i = 5时,x = 1;

当i = 6时,x < 1;          (所以i最大为5)


好了,咱们看题 大笑

03:复杂的整数划分问题


总时间限制:
200ms
内存限制:
65536kB
描述

将正整数n表示成一系列正整数之和,n=n1+n2+…+nk,其中n1>=n2>=…>=nk>=1k>=1
正整数n的这种表示称为正整数n的划分。

输入
标准的输入包含若干组测试数据。每组测试数据是一行输入数据,包括两个整数N 和 K。
(0 < N <= 50, 0 < K <= N)
输出
对于每组测试数据,输出以下三行数据:
第一行: N划分成K个正整数之和的划分数目
第二行: N划分成若干个不同正整数之和的划分数目
第三行: N划分成若干个奇正整数之和的划分数目
样例输入
5 2
样例输出
233
提示
第一行: 4+1, 3+2,
第二行: 5,4+1,3+2
第三行: 5,1+1+3, 1+1+1+1+1+1




#include <iostream>#include <cstdio>#include <queue>#include <vector>#include <map>using namespace std;int main(){    int n, k;    while( cin >> n >> k )    {        int num[n+1][n+1];             // 表示把n分成k个数的dp数组;        int num1[n+1][n+1];            // 表示把n分成不相等正整数的dp数组;        int g[55][55], f[55][55];      // g数组为偶数dp数组, f数组为奇数dp数组;        int i, j;                                    // 初始化;        for( i=0; i<=n; i++ )        {            for( j=0; j<=n; j++ )            {                num[i][j] = num1[i][j] = f[i][j] = g[i][j] = 0;            }        }                                    // 这就是上面说的其中两种。        for( i=1; i<=n; i++)        {            for( j=1; j<=n; j++)            {                if( i < j )                {                    num[i][j] = 0;                    num1[i][j] = num1[i][j-1];                }                if( i == j )                {                    num[i][j] = 1;                    num1[i][j] = 1 + num1[i][j-1];                }                if( i > j )                {                    num[i][j] = num[i-1][j-1] + num[i-j][j];                    num1[i][j] = num1[i-j][j-1] + num1[i][j-1];                }            }        }                                 //  这里是最晕的,只要记住就好了,搞懂也没多大意义;        f[0][0]=1; g[0][0]=1;        for( i=1; i<=n; i++ )        {            for( j=1; j<=i; j++)            {                g[i][j] = f[i-j][j];                f[i][j] = f[i-1][j-1] + g[i-j][j];            }        }        cout << num[n][k] <<endl;        cout << num1[n][n] <<endl;        int sum = 0;        for( i=0; i<=n; i++)            sum += f[n][i];        cout << sum <<endl;    }    return 0;}





1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 摩托车转向灯不会打怎么办 浓硫酸弄到脸上怎么办 钥匙被锁在家里怎么办 有奶宝宝吸不出来怎么办 奶涨宝宝吸不出来怎么办 高铁票未取误点怎么办 飞猪上12306占座失败怎么办? 新生儿肚脐还没有脱落发炎怎么办 蹲坑被纸巾堵了怎么办 老公有外遇老婆不想离婚怎么办 结婚十年妻子出轨该怎么办 初生儿眼睛多眼屎怎么办 被丝袜脚摩擦过瘾了怎么办 老公在卧室装摄像头怎么办 听了鬼故事害怕怎么办 看完鬼片害怕睡不着怎么办 晚上看了鬼片怎么办 说话不经过大脑考虑怎么办 我太受欢迎了怎么办动漫结局 狗胃不好总呕吐怎么办 比格犬晚上叫怎么办 玻尿酸隆鼻变宽了怎么办 打玻尿酸鼻子变宽怎么办 鼻炎的人感冒了怎么办 小孩上幼儿园反复感冒怎么办 3岁宝宝感冒鼻炎怎么办 鼻炎犯了鼻子不通气怎么办 食物呛到鼻子里怎么办 胃疼引起的焦虑怎么办 泰迪犬发生口腔亏痒怎么办? 俩鼻子都堵了怎么办 2岁宝宝鼻甲肿大怎么办 感冒10多天不好怎么办 宝妈鼻炎犯了怎么办 鼻炎犯了好多黄鼻涕怎么办 空调吹多了上火怎么办 宝宝感冒鼻塞流鼻涕口臭怎么办 怀孕了有鼻息肉怎么办 孕晚期鼻炎犯了怎么办 孕妇鼻炎犯了头疼怎么办 一岁宝宝有鼻炎怎么办