• 51Nod 1201-整数划分


    原题

    Description

    将N分为若干个不同整数的和,有多少种不同的划分方式

    例如:n = 6,{6} {1,5} {2,4} {1,2,3},共4种。

    由于数据较大,输出Mod 10^9 + 7的结果即可。

    Input

    输入1个数N(1 <= N <= 50000)。

    Output

    输出划分的数量Mod 10^9 + 7。

    Sample Input

    6

    Sample Output

    4

    题意

    求自然数n划分为正整数的所有方案数。

    题解

    这道题与CodeVS的“数的划分”十分类似,但那道题求的是:将n分成m份的方案数,并且每份是可以相同的;而这道题却要求所有划分方法的划分方案的总数,并且每份不能相同。满足这种要求的最大数也就是1+2+3+4+...+m<=n,而题目规定n<=50000,所以(1+m)*m/2<=50000,解得m<316,所以最多只能将n分成316份,这样便大大缩小了数组的大小范围。

    有了m的范围,我们便可以定义一个F数组[0..50000,1..316],F[i][j]表示将数i分为j份的方案数总和。

    于是便有了状态转移方程:f[i][j]:=f[i-j,j]+f[i-j,j-1]。

    下面来具体解释一下这个方程:

    1、f[i-j,j]表示的是将i分为不包含1(min>=2)的方案总个数,例如,6(=9-3)分成3份可以分为{1,2,3},则9可以分为{1+1,2+1,3+1}->{2,3,4}【仅1种

    2、f[i-j,j-1]表示的是将i分为包含1(min=1)的方案总个数,例如,6=(=9-3)分成2(=3-1)可以分为{0,1,5}{0,2,4},则9可以分为{0+1,1+1,5+1}{0+1,2+1,4+1}->{1,2,6}{1,3,5}【共2种   

    至于为什么状态转移方程的f[i-j,j-1]与“数的划分”中的f[i-1,j-1]存在着区别,其根本原因是,一个可以分成相同的数,而另一个则不能。多减的这(j-1)其实是为了保证划分中的数据不存在重复并一定从小到大排列。

    pia代码:

     1 var f:array[0..50000,0..316] of longint;
     2 var n,i,j,ans:longint;
     3 begin
     4   readln(n);
     5   f[0,0]:=1;//初始化
     6   for i:=1 to n do//被分的数
     7   for j:=1 to 316 do//分后的个数
     8   if i>=j then f[i,j]:=(f[i-j,j]+f[i-j,j-1]) mod 1000000007;
     9   for i:=1 to 316 do ans:=(ans+f[n,i]) mod 1000000007;
    10   writeln(ans);
    11 end.
    51Nod 1201-整数划分

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    [译]Vulkan教程(09)窗口表面
    [译]Vulkan教程(08)逻辑设备和队列
    [译]Vulkan教程(07)物理设备和队列家族
    Linux命令行文本工具
    go语言周边
    go第三方常用包
    Centos6安装gcc4.8及以上版本
    pyenv设置python多版本环境
    Redis慢日志
    PHP-CPP开发扩展(七)
  • 原文地址:https://www.cnblogs.com/HAdolf-HQY/p/6323034.html
Copyright © 2020-2023  润新知