51nod 1201 整数划分(dp)

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1201

题解:显然是一道dp,不妨设dp[i][j]表示数字i分成j个一共有几种分法。

那么转移方程式为:

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

表示将i - 1划分为j个数,然后j个数都+1 还是不重复,将i - 1划分为j - 1个数,然后j - 1个数都+1,再加上1这个数。

然后就是j的范围要知道1+2+3+.....+n=i显然(1+n)*n/2=i,所以j的范围最多就是sqrt(i)。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#define mod 1000000007
using namespace std;
const int M = 5e4 + 10;
int dp[M][400];
int main() {
    int n;
    scanf("%d" , &n);
    memset(dp , 0 , sizeof(dp));
    dp[1][1] = 1 , dp[2][1] = 1 , dp[3][2] = 1 , dp[3][1] = 1;
    for(int i = 4 ; i < M ; i++) {
        for(int j = 1 ; j <= sqrt(2 * i) ; j++) {
            dp[i][j] = dp[i - j][j] + dp[i - j][j - 1];
            dp[i][j] %= mod;
        }
    }
    int sum = 0;
    for(int i = 1 ; i <= sqrt(2 * n) ; i++) {
        sum += dp[n][i];
        sum %= mod;
    }
    printf("%d\n" , (sum + mod) % mod);
    return 0;
}
时间: 2024-10-25 16:58:03

51nod 1201 整数划分(dp)的相关文章

51nod p1201 整数划分

1201 整数划分 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 将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. Input示例 6 Output示例 4 分析:这题关键在于不同的整数一个包含数字最多的划分必

bzoj 3612: [Heoi2014]平衡【整数划分dp】

其实就是-n~n中求选k个不同的数,和为0的方案数 学到了新姿势叫整数划分,具体实现是dp 详见:https://blog.csdn.net/Vmurder/article/details/42551603 设f[i][j]为j个数和为i的方案数,然后因为互不相同,所以转移的话有两种,就是当前j个数全部+1,和当前j个数全部+1并且多填一个1出来,也就是f[i][j]=f[i-j][j]+f[i-j][j-1] 但是这里要求选的数不能超过n,我们考虑i>n的f中一定有一个大于n的数,我们把这种情

整数划分dp

整数划分 --- 一个老生长谈的问题: 1) 练练组合数学能力. 2) 练练递归思想 3) 练练DP 总之是一道经典的不能再经典的题目: 这道好题求: 1. 将n划分成若干正整数之和的划分数. 2. 将n划分成k个正整数之和的划分数. 3. 将n划分成最大数不超过k的划分数. 4. 将n划分成若干奇正整数之和的划分数. 5. 将n划分成若干不同整数之和的划分数. 1.将n划分成不大于m的划分法: 1).若是划分多个整数可以存在相同的: dp[n][m]= dp[n][m-1]+ dp[n-m][

hdu 5230 整数划分 dp

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5230 题意:给定n,c,l,r.求有多少种方法从1~n-1选取任意k数每个数的权重为其下标,使得这些数字之和加上c之后在l,r范围内. 题解:第一反应是计数01包,但是范围给定的n太大,TLE... 然后仔细想想,不就是求l~r范围内不重复的整数划分数嘛. dp[i][j]表示j这个数字,当前的拆分拥有i个拆分数时的方案数. 先考虑允许重复数字 : dp[i][j] = dp[i][j - i] + d

51nod1201 整数划分

01背包显然超时.然后就是一道神dp了.dp[i][j]表示j个数组成i的方案数.O(nsqrt(n)) #include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i-

整数划分 (区间DP)

整数划分(四) 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 暑假来了,hrdv 又要留学校在参加ACM集训了,集训的生活非常Happy(ps:你懂得),可是他最近遇到了一个难题,让他百思不得其解,他非常郁闷..亲爱的你能帮帮他吗? 问题是我们经常见到的整数划分,给出两个整数 n , m ,要求在 n 中加入m - 1 个乘号,将n分成m段,求出这m段的最大乘积 输入 第一行是一个整数T,表示有T组测试数据接下来T行,每行有两个正整数 n,m ( 1<= n <

51nod 1201 (dp)

整数划分 将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. Input示例 6 Output示例 4[分析]注意到划分后,每个集合里数的个数不超多350个,然后考虑dp[i][j]表示将数字i化成j个数相加, 然后将这j个数每个数+1,即可得到数字

NYOJ746——整数划分(四)

整数划分(四) 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 暑假来了,hrdv 又要留学校在参加ACM集训了,集训的生活非常Happy(ps:你懂得),可是他最近遇到了一个难题,让他百思不得其解,他非常郁闷..亲爱的你能帮帮他吗? 问题是我们经常见到的整数划分,给出两个整数 n , m ,要求在 n 中加入m - 1 个乘号,将n分成m段,求出这m段的最大乘积 输入 第一行是一个整数T,表示有T组测试数据 接下来T行,每行有两个正整数 n,m ( 1<= n <

NYOJ-571 整数划分(三)

此题是个非常经典的题目,这个题目包含了整数划分(一)和整数划分(二)的所有情形,而且还增加了其它的情形,主要是用递归或者说是递推式来解,只要找到了递推式剩下的任务就是找边界条件了,我觉得边界也是非常重要的一步,如果找不准边界,这个题也很难做出来,当时我就是找边界找了好长时间,边界得琢磨琢磨.递推步骤如下: 第一行:将n划分成若干正整数之和的划分数.状态转移方程:dp[i][j]:和为i.最大数不超过j的拆分数dp[i][j]可以分为两种情况:1.拆分项至少有一个j 2.拆分项一个j也没有dp[i