c语言10个数分成两组份法,将整数n分成k份,且每份不能为空,任意两种分法不能相同(不考虑顺序)【划分问题】...

将整数n分成k份,且每份不能为空,任意两种分法不能相同(不考虑顺序)。

例如:n=7,k=3,下面三种分法被认为是相同的:

1,1,5; 1,5,1; 5,1,1。

问有多少种不同的分法。

输入:n,k(6

输出:一个整数,即不同的分法。

输入输出样例

输入:

7 3

输出:

4

典型的划分DP问题。http://codevs.cn/wiki/solution/?problem_id=1039

//dp[i][j]=dp[i][j-i]+dp[i-1][j-1];

//假设这所有前i份最底层的1都不去动它,那么

//dp[i][j-i]是指第i份个数大于1的时候的方法数

//dp[i-1][j-1]是指第i份个数等于1的时候的方法数

#include

using namespace std;

int n,m,dp[10][205];

int main(){

scanf("%d %d",&n,&m);

dp[0][0]=1;

for(int i=1;i<=m;i++){

for(int j=i;j<=n;j++){

dp[i][j]=dp[i][j-i]+dp[i-1][j-1];

}

}

printf("%d\n",dp[m][n]);

return 0;

}

个人认为这种写法理解起来会比较简单:

#include

using namespace std;

int n,m,dp[10][205];

int main(){

scanf("%d %d",&n,&m);

dp[1][1]=1;

for(int i=1;i<=m;++i){

for(int j=i;j<=n;++j){

if(j+i<=n)

dp[i][j+i]+=dp[i][j]; //所有点上面再铺一层

dp[i+1][j+1]+=dp[i][j]; //再增加一份,个数是1

}

}

printf("%d\n",dp[m][n]);

return 0;

}

不得不感慨编程之美乃造物者之无尽藏也。。。

一次掷n个骰子,每个骰子有p个面,问有多少种情况?

2个骰子,3个面,1,1,2和2,1,1是一种情况

对于这种情形 我们一般进行排序处理 把所有情况所对应的数从小到大排序

a1<=a2<=a3<=...<=an

比如1,1,2和2,1,1就相当于1,1,2了

再比如 3,1,2 2,3,1 都相当于1,2,3

这样每种情况都与一个序列一一对应不是吗?

下面我们求排列数

n个骰子,每个骰子有p个面 那么我们只要知道这p个面 每个面出现了多少次,依据上述的排序规则 这个序列就确定了

然后就转化成了一个方程

x1+x2+x3+...xp=n 有多少组非负整数解

(xi代表第i个面出现了多少次)

对于这个方程 我们令ai=xi+1

则x1+x2+x3+...xp=n的非负数解与方程 a1+a2+a3+...ap=n+p的正数解一一对应

a1+a2+a3+...ap=n+p 这个方程的正数有多少组解呢? 答案是C(n+p-1,p-1)种

因为可以看成是有n+p个1 然后中间插入p-1个板子 隔板法求得方程的解数

所以一次掷n个骰子,每个骰子有p个面 有C(n+p-1,p-1)种情况.

附动态规划方程

dp[i][j] 前i个筛子 第i个筛子面值为j的方法数目

dp[1][j]=1 (1<=j<=p)

dp[i][j]=Sigma(dp[ i-1

][k]) i>1 1<=k<=j

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值