NYOJ 651 —— n划分为2个以上不同正整数的划分个数

Cut the rope

时间限制:1000 ms  |  内存限制:65535 KB

描述

We have a rope whose length is L. We will cut the rope into two or more parts, the length of each part must be an integer, and no two parts have the same length.
  Your task is to calculate there exists how many results after the cutting. We say two results are different if and only if there is at least one part, which we can find in one result but can not find in the other result

输入
There is an integer T (1 <= T <= 50000) in the first line, which indicates there are T test cases in total.
  For each test case, there is only one integer L (1 <= L <= 50000) which has the same meaning as above.
输出
For each test case, you should output the correct answer of the above task in one line.
  Because the answer may be very large, you should just output the remainder of it divided by 1000000 instead
样例输入
3
2
3
6
样例输出
0
1
3

  这题对时间和空间的限制很高,所以,我们要尽力优化才行。

  一般的,求n划分为不同正整数的划分个数,这个问题可以通过dp来解决,定义dp[i][j]为i划分为不大于j的划分个数。但是,这里会遇到一个很棘手的问题:1 ≤ n ≤ 50000,所以如果按照这种状态的定义,空间、时间复杂度达到25*108,时间、空间都会超过限制!

  所以,一般的做法行不通。换一个思路:题目其实也是在求n划分为2、3、...个不同正整数的划分个数之和。

  求n划分为k个正整数的划分个数,这个问题也可以用dp来解决:定义dp[i][j]为i划分为j个不同正整数的划分个数。

  i的取值范围仍为[1, 50000],那么j的范围呢?即,i最多可以被划分为多少份呢?

  假设我们将i划分成了j份,那么在i取最小的情况下,i=1+2+...+j (划分的每个元素都要不相同) = (1+j)*j/2。因为i ≤ 50000,所以j最多取到316,而不可能分得更多了,再分就要出现相同的了。故,j ≤ 316

  时间、空间大小降为316*50000=1.58*107,因为系数较小,可以AC

#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
using namespace std;

const int MAXN = 50005;
const int MOD = 1000000;
int dp[MAXN][317];

void init()
{
    dp[1][1] = 1;
    for(int i=2; i<316; i++)
        dp[1][i] = 0;

    for(int i=2; i<MAXN; i++) {
        for(int j=1; j<317; j++) {
            if(j>=i)    dp[i][j] = 0;
            else    dp[i][j] = (dp[i-j][j-1] + dp[i-j][j])%MOD;
        }
    }
}

int main ()
{
    init();

    int T, n, ans;
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        ans = 0;
        for(int i=2; i<317; i++)    ans = (ans + dp[n][i]) % MOD;
        printf("%d\n", ans);
    }
    return 0;
}
时间: 2024-12-16 21:50:35

NYOJ 651 —— n划分为2个以上不同正整数的划分个数的相关文章

NYOJ 1103 —— m划分为n个正整数的个数

多边形划分 时间限制:1000 ms  |  内存限制:65535 KB 描述 Give you a convex(凸边形), diagonal n-3 disjoint divided into n-2 triangles(直线), for different number of methods, such as n=5, there are 5 kinds of partition method, as shown in Figure 输入 The first line of the inp

NYOJ 90 —— 求n划分为若干个正整数的划分个数

整数划分 时间限制:3000 ms  |  内存限制:65535 KB 描述 将正整数n表示成一系列正整数之和:n=n1+n2+…+nk, 其中n1≥n2≥…≥nk≥1,k≥1. 正整数n的这种表示称为正整数n的划分.求正整数n的不 同划分个数. 例如正整数6有如下11种不同的划分: 6: 5+1: 4+2,4+1+1: 3+3,3+2+1,3+1+1+1: 2+2+2,2+2+1+1,2+1+1+1+1: 1+1+1+1+1+1.  输入 第一行是测试数据的数目M(1<=M<=10).以下每

47、软件需求工程的活动可以划分为5个独立的阶段:需求获取、需求建模、形成需求规格、需求验证和需求管理,需求建模是()

2013年下半年软考高级信息系统项目管理师综合知识真题答案与解析: 47.软件需求工程的活动可以划分为5个独立的阶段:需求获取.需求建模.形成需求规格.需求验证和需求管理,需求建模是() A.分析需求的正确性和可行性的过程 B.对需求的抽象描述 C.对生成需求模型构件的精确的形式化的描述 D.开发.捕获和修订用户的需求 信管网参考答案:B 信管网解析: 需求建模就是需求分析过程,目的是对各种需求信息进行分析并抽象描述,为目标系统建立一个概念模型.软件需求工程活动的5个阶段:http://www.

NYOJ 746 - 正整数n划分为m段,求m段的最大乘积 【区间DP】

整数划分(四) 时间限制:1000 ms  |  内存限制:65535 KB 描述 给出两个整数 n , m ,要求在 n 中加入m - 1 个乘号,将n分成m段,求出这m段的最大乘积 输入 第一行是一个整数T,表示有T组测试数据接下来T行,每行有两个正整数 n,m ( 1<= n < 10^19, 0 < m <= n的位数): 输出 输出每组测试样例结果为一个整数占一行 样例输入 2 111 2 1111 2 样例输出 11 121 #include <cstdio>

410. Split Array Largest Sum 把数组划分为m组,怎样使最大和最小

[抄题]: Given an array which consists of non-negative integers and an integer m, you can split the array into m non-empty continuous subarrays. Write an algorithm to minimize the largest sum among these m subarrays. Note:If n is the length of array, as

Java把内存划分为4个部分 1. 代码区 1、栈区 3、堆区 4、静态区域

1.栈区(stacksegment)—由编译器自动分配释放,存放函数的参数值,局部变量的值等,具体方法执行结束之后,系统自动释放JVM内存资源 2.堆区(heapsegment)—一般由程序员分配释放,存放由new创建的对象和数组,jvm不定时查看这个对象,如果没有引用指向这个对象就回收 3.静态区(datasegment)—存放全局变量,静态变量和字符串常量,不释放 4.代码区(codesegment)—存放程序中方法的二进制代码,而且是多个对象共享一个代码空间区域

[Swift]LeetCode698. 划分为k个相等的子集 | Partition to K Equal Sum Subsets

Given an array of integers nums and a positive integer k, find whether it's possible to divide this array into k non-empty subsets whose sums are all equal. Example 1: Input: nums = [4, 3, 2, 3, 5, 2, 1], k = 4 Output: True Explanation: It's possible

划分为k个相等的子集

给定一个整数数组  nums 和一个正整数 k,找出是否有可能把这个数组分成 k 个非空子集,其总和都相等. 示例 1: 输入: nums = [4, 3, 2, 3, 5, 2, 1], k = 4输出: True说明: 有可能将其分成 4 个子集(5),(1,4),(2,3),(2,3)等于总和. 注意: 1 <= k <= len(nums) <= 160 < nums[i] < 10000 class Solution { private: bool canParti

n个数分为两组,两组数的个数尽可能相等,差值最小

题目描述:对于有n个数的数组,分为两组,这两组的数的个数尽可能相等(不超过1),同时两组的数之和的差值最小. 这个题目使用类似0-1背包问题,思路:从k个数中选i个数,求所有可能的和,并把这些和放在flag中用true表示.(k,i,flag见代码) 1 public static void main(String[] args){ 2 int[] arr = {1 , 2 , 3 , 5 , 7 , 8 , 9}; 3 int n = 7; 4 int sum = 0; 5 for(int i