zoukankan      html  css  js  c++  java
  • n的m划分递推

    http://www.hankcs.com/program/m-n-recursive-division.html

    有n个无区别的物品,将它们划分为不超过m组,求出划分方法数模M的余数。

    限制条件:

    1≤m≤n≤1000

    2≤M≤10000

    输入

    n = 4

    m = 3

    M = 10000

    输出:

    4 (1 + 1 + 2 = 1 + 3 = 2 + 2 = 4)

    这样的划分被称作n的m划分,特别的,m = n时被称作n的划分数。在此我们定义如下:

    dp[i][j] = j 的 i 划分的总数

    递推关系的难点在于不重复。我们采用一种标准将问题化为子问题,这个标准需要用到一种新的定义。我们定义n的m划分具体为一个集合{ai},{ai}满足∑mi=1 ai = n 。可以看出{ai}里一共有m个数,这m个数不一定大于0。

    这个标准是:是否存在某个ai=0;这样可以将{ai}分为两种情况:

    1、不存在某个ai=0

    此时{ai}的个数等于{ai – 1}的个数,即 n – m 的 m 划分。理解起来并不难,集合里每个数都减去1,一共减了m个。

    此时dp[i][j] = dp[i][j – i] 。

    2、存在某个ai=0

    此时{ai}的个数等于 n 的 m – 1 划分。可以这样思考,存在ai=0,说明划分一定不足m组,那么至少可以少分一组同时满足划分数相同。

    此时dp[i][j] = dp[i – 1][j] 。

    那么{ai}总的划分数就是这两种情况的综合,dp[i][j] = dp[i][j – i] + dp[i – 1][j]。

     1 int n, m;
     2 int dp[MAX_M + 1][MAX_N + 1];
     3 void solve()
     4 {
     5     dp[0][0] = 1;
     6     for(int i = 1; i <= m; i++)
     7     {
     8         for(int j = 0; j <= n; j++)
     9         {
    10             if(j - i >= 0)
    11                 dp[i][j] = (dp[i - 1][j] + dp[i][j - 1]) % M;
    12             else
    13                 dp[i][j] = dp[i - 1][j];
    14         }
    15     }
    16 }
  • 相关阅读:
    MySQL 数据恢复
    由 go orm 引发的探索
    beego 优雅重启
    2020年8月20日
    Linux 递归获取目录下所有满足条件的文件
    NET Core Kestrel部署HTTPS 一个服务器绑一个证书 一个服务器绑多个证书
    Flutter环境配置-windows
    Vue获取钉钉免登陆授权码(vue中的回调函数实践)
    【C#上位机必看】你们要的Iot物联网项目来了
    Windows Server系统部署MySQL数据库
  • 原文地址:https://www.cnblogs.com/CZT-TS/p/8633530.html
Copyright © 2011-2022 走看看