zoukankan      html  css  js  c++  java
  • 51nod1201_dp思维题

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1201

    将N分为若干个不同整数的和,有多少种不同的划分方式,例如:n = 6,{6} {1,5} {2,4} {1,2,3},共4种。由于数据较大,输出Mod 10^9 + 7的结果即可。

    分析:这题关键在于不同的整数
    一个包含数字最多的划分必定是1+2+3+....+m == n
    这样(m + 1) * m <= 2 * n
    可以确定m是O(sqrt(n))级别的
    想到这里很容易想到用dp[i][j]表示I这个数分成j的数组成的划分有多少种。
    方程为:dp[i][j] = dp[i - j][j] + dp[i - j][j - 1]
    前者表示将i - j划分为j个数,每个数加1就是i划分为j个数的方案了。
    但是前者这样有i-j的方案+1形成i分为j个数的方案是不完全的,因为没有1
    后者则补充了这部分的答案,表示i-j划分为j个数,每个数+1,并且方案再加入一个1这个元素。
    由于数不重复,所以1的个数只能为1个。
     1 #include <algorithm>
     2 #include <iostream>
     3 #include <cstring>
     4 #include <cstdlib>
     5 #include <cstdio>
     6 #include <vector>
     7 #include <ctime>
     8 #include <cmath>
     9 #include <queue>
    10 #include <list>
    11 #include <set>
    12 #include <map>
    13 using namespace std;
    14 typedef long long LL;
    15 const int mod = 1e9 + 7;
    16 int dp[50010][350];
    17 int main()
    18 {
    19     int n;
    20     scanf("%d", &n);
    21     int m = sqrt(2 * n);
    22     memset(dp, 0, sizeof(dp));
    23     dp[0][0] = 1;
    24     for(int j = 1; j <= m; j++)
    25     {
    26         for(int i = j; i <= n; i++)
    27         {
    28             dp[i][j] = (dp[i-j][j] + dp[i-j][j-1]) % mod;
    29             //cout << i <<" "<<j << " "<<dp[i][j]<<endl;
    30         }
    31     }
    32     int res = 0;
    33     for(int i = 1; i <= m; i++)
    34         res = (res + dp[n][i]) % mod;
    35     printf("%d
    ", res);
    36     return 0;
    37 }
    View Code
  • 相关阅读:
    python斐波那契数列
    python装饰器
    Python文件操作
    python 第三方库的安装方法
    Ajax 基本使用学习记录
    微分方程概述
    Typora中的数学公式
    Ubuntu20.04 安装 mysql8.0 之后 root 账户无法登录
    Ubuntu20.04换源之后依旧慢?如何更有效的换源
    Ubuntu18.04更新python版本
  • 原文地址:https://www.cnblogs.com/luomi/p/5904431.html
Copyright © 2011-2022 走看看