nyoj_871(规律(数学(排列组合(dp)

题目如下:

题目详情 - 湮灭残昼 - 南阳理工学院OJ (nyist.edu.cn)

题目大意为:输入m和n    解出n个非负数的整数的和为m的解的个数 (注意是非负数  含零  比赛时就没认真读好题以为不含零)其中只要有一个数不同则作为不同解  比如m=2 n=2 那么 0 2 和2 0被认为是两组解

在看到题目的那一刻,我也是懵逼的,无思路,但该题明显就是个数学问题,可以试着找找规律看看,那么就从打表开始吧:我们可以先打几组解看看能不能看出点东西

小数据甚至可以通过多个for循环找出来(其实赛时我也想过直接打表然后printf 但最后发现数太大最后放弃

m\n123456
1123456
2136101521
31410203556
415153570126
5162156126252
6172884210462

虽然题目数据给的为n<=m 但我们可以扩大范围找规律

在打了个6*6的表后,我们不难发现(学过动态规划)好像确实有点规律?比如m=4和n=4的答案是m=4 n=3和m=3 n=4的和 即jay[4][4]=jay[4][3]+jay[3][4]再多看几组发现好像都可以满足这个式子dp[m][n]=dp[m-1][n]+dp[m][n-1]那么答案就可以的出来了

但又有人说了 没学过dp或者根本没看出来时dp怎么办 那么就可以用排列组合解决此问题,因为我们通过观察每个答案,好像不无规律?

比如当m=1时不管n=?即答案都为n

n=1 m=?时答案都为1

此时我们好像发现了 好像与高中学过的排列组合相同?

也就是这个东西

 我们发现当n=1时Cm n均为m

当n=0时Cm n均为1

好像与上面照应住了

那我们通过表上对应的每个数 得出一个结论 答案为

 此时我们好像发现,与高中数学中学的排列组合里面的隔板法有点像

那么就会有人要说了 要是在高中(智力巅峰,我分分钟解决这个问题

但现在我是大学生 (干饭巅峰

 那么我们来重新回忆一下隔板法

直接上例题ba:

有10个相同的球,要放进3个不同盒子里,并允许空盒子 求总的方案数(隔板法

乍一看好像没什么思路?因为是允许有空盒子存在

那换一道例题再看看:

有7个相同的球 放进三个不同的盒子里 每个盒子至少有一个球(插空法

隔板法不熟悉,那这个我们还不熟悉?高中成天用的插空法

7个球,有8个空,因为不可空,所以两端不能再选,于是就相当于剩下6个空 那么只需要插2个空就可以分成三份

那么答案就是C6 2 =15

所以插空法的模板就是 m个球 放进n个不同盒子 盒子至少有一个球

答案为:

 那么我们可以回到最上面的题

有10个相同的球,要放进3个不同盒子里,并允许空盒子 求总的方案数

因为该题是允许有空盒子存在,所以不能直接用公式 那么我们可以换个思路看看

把每个盒子都加一

那么就变成了有13个相同的球,要放进3个不同盒子里,每个盒子至少一个球 求总的方案数

那么答案就很显然 直接就为Cm-1 n-1了

此时我们推出来了隔板法  

我们可以将隔板法总结为    求n个数(非负数)的和为m的总方案数

那么我们就发现和题目的意思一模一样

所以该题就是隔板法 只不过是用代码实现而已  

公式确实是这样  但我们如果硬求某个数的阶乘 可能会爆(数太大

所以我们要优化 要乘着化简着

例如C9 3=9*8*7/3*2*1=9/1*8/2*7/3

 

 隔板法AC代码如下

 

 我们要注意 此时为什么不开int类型  

我们可以举一组例子,比如C9 3=9/1*8/2*7/3

如果用int类型 那么7/3则会默认向下取整为2

但实际并不为2 所以如果用int 可能会直接的wrong answer

所以我们要用double类型 来确保每次相乘不会使答案发生改变

dpAC代码如下:

 注意m=1和n=1时要把数组初始化完毕

谢谢观看,有什么不足之处多多指教

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

那也是别人的以为

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值