zoukankan      html  css  js  c++  java
  • HDU-1028 Ignatius and the Princess III

           整数拆分题目:

        http://acm.hdu.edu.cn/showproblem.php?pid=1028

               Ignatius and the Princess III

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 10429    Accepted Submission(s): 7398

    Problem Description
    "Well, it seems the first problem is too easy. I will let you know how foolish you are later." feng5166 says.
    "The second problem is, given an positive integer N, we define an equation like this:   N=a[1]+a[2]+a[3]+...+a[m];   a[i]>0,1<=m<=N; My question is how many different equations you can find for a given N. For example, assume N is 4, we can find:   4 = 4;   4 = 3 + 1;   4 = 2 + 2;   4 = 2 + 1 + 1;   4 = 1 + 1 + 1 + 1; so the result is 5 when N is 4. Note that "4 = 3 + 1" and "4 = 1 + 3" is the same in this problem. Now, you do it!"
     
    Input
    The input contains several test cases. Each test case contains a positive integer N(1<=N<=120) which is mentioned above. The input is terminated by the end of file.
     
    Output
    For each test case, you have to output a line contains an integer P which indicate the different equations you have found.
     
    Sample Input
    4
    10
    20
     
    Sample Output
    5
    42
    627
     
    Author
    Ignatius.L
     整数划分的递归算法:
    int split(int n, int m)
    {
     if(n < 1 || m < 1)
      return 0;
     if(n == 1 || m == 1)
      return 1;
     if(n < m) 
      return split(n, n);
     if(n == m) 
      return (split(n, m - 1) + 1);
     if(n > m)
      return (split(n, m - 1) + split((n - m), m));
    }

    递归算法易于理解。但是由于多次重复计算,会很浪费时间。所以需要转化成非递归的算法。如下:

     

    首先,我们引进一个小小概念来方便描述吧,record[n][m]是把自然数划划分成所有元素不大于m的分法,例如:

    当n=4,m=1时,要求所有的元素都比m小,所以划分法只有1种:{1,1,1,1};

    当n=4,m=2时,。。。。。。。。。。。。。。。。只有3种{1,1,1,1},{2,1,1},{2,2};

    当n=4,m=3时,。。。。。。。。。。。。。。。。只有4种{1,1,1,1},{2,1,1},{2,2},{3,1};

    当n=4,m=5时,。。。。。。。。。。。。。。。。只有5种{1,1,1,1},{2,1,1},{2,2},{3,1},{4};

    从上面我们可以发现:当n==1||m==1时,只有一种分法;

    当n<m时,由于分法不可能出现负数,所以record[n][m]=record[n][n];

    当n==m时,那么就得分析是否要分出m这一个数,如果要分那就只有一种{m},要是不分,那就是把n分成不大于m-1的若干份;即record[n][n]=1+record[n][n-1];

    当n>m时,那么就得分析是否要分出m这一个数,如果要分那就{{m},{x1,x2,x3..}}时n-m的分法record[n-m][m],要是不分,那就是把n分成不大于m-1的若干份;即record[n][n]=record[n-m][m]+record[n][m-1];

    #include<stdio.h>
    int dp[150][150]={0}; 
    int main()
    {
        int i,j;
        for(i=1;i<=121;i++)
           dp[1][i]=dp[i][1]=1;
        for(i=2;i<121;i++)
        {
            for(j=2;j<=121;j++)
            {
                if(i<j) 
              dp[i][j]=dp[i][i];
                else if(i==j)
               dp[i][j]=1+dp[i][j-1];
                else if(i>j) 
            dp[i][j]=dp[i-j][j]+dp[i][j-1];
         }
        }
               int n;
        while(~scanf("%d",&n))
              printf("%d
    ",dp[n][n]);
        return 0;
    }

    利用母函数,但是,比较费时。

    #include <stdio.h>
    const int lmax=10000;    
    int c1[lmax+1],c2[lmax+1];
    int main()
    {
     int n,i,j,k;
     while (~scanf("%d",&n))
     {
      for (i=0;i<=n;i++)
       {
       c1[i]=0;
       c2[i]=0;
      }
       for(i=0;i<=n;i++) 
        c1[i]=1;
       for(i=2;i<=n;i++)
       { 
        for(j=0;j<=n;j++)
         for(k=0;k+j<=n;k+=i)
         {
          c2[j+k]+=c1[j];  
         }
         for (j=0;j<=n;j++)
         {  
          c1[j]=c2[j];
          c2[j]=0; 
         }
       }
       printf("%d
    ",c1[n]);
     }
     return 0;
    }

     

  • 相关阅读:
    Python/WSGI 应用快速入门--转
    汇编题目:数字转字符,并在窗口上显示出来
    汇编题目:在窗口上显示Welcome to masm!
    VBA中的函数Timer用法
    用VBA计算两个日期之间的工作日(去掉周末两天)
    VBA记录当前系统时间并精确到毫秒
    上海房产税免征--积分或居住证
    学习汇编语言
    “Hello World”—— 第一个汇编程序
    汇编程序设计上机步骤
  • 原文地址:https://www.cnblogs.com/cancangood/p/3361459.html
Copyright © 2011-2022 走看看