整数划分问题

题目信息我要加题 回到首页

整数划分问题

整数划分是一个经典的问题。希望这道题会对你的组合数学的解题能力有所帮助。 

Input 

每组输入是两个整数n和k。(1 <= n <= 50, 1 <= k <= n) 

Output 

对于每组输入,请输出六行。 

第一行: 将n划分成若干正整数之和的划分数。 
第二行: 将n划分成k个正整数之和的划分数。 
第三行: 将n划分成最大数不超过k的划分数。 
第四行: 将n划分成若干奇正整数之和的划分数。 
第五行: 将n划分成若干不同整数之和的划分数。 
第六行: 打印一个空行。 

Sample Input 
5 2

Sample Output 
7
2
3
3
3


Hint: 
1、将5划分成若干正整数之和的划分为: 5, 4+1, 3+2, 3+1+1, 2+2+1, 2+1+1+1, 1+1+1+1+1 
2、将5划分成2个正整数之和的划分为: 3+2, 4+1 
3、将5划分成最大数不超过2的划分为: 1+1+1+1+1, 1+1+1+2, 1+2+2 
4、将5划分成若干奇正整数之和的划分为: 5, 1+1+3, 1+1+1+1+1 
5、将5划分成若干不同整数之和的划分为: 5, 1+4, 2+3 

最新评论发表评论

您尚未登录本站,不能发表评论,请登录 或者 注册 成为本站会员

评论人: tanpan004  发布时间: 2012-4-27 17:59:43
// 整数划分.cpp : 定义控制台应用程序的入口点。
//

#include "stdio.h"

int sum[5];
int num[1000];
int num_max=0;

void f(int n,int k)
{
  if(n==0)
  {
     int flag=0,kmax=0,flag1=0;

      for(int i=0;i<num_max ;i++) 
      {
          if(num[i]<num[i+1]) {num_max--; return;}
      }

      for(int i=0;i<num_max ;i++) 
      { 
        if(num[i]>kmax) kmax=num[i];
        if(num[i]%2==0) flag=1;
        for(int j=i+1;j<num_max;j++) 
            if(num[i]==num[j]) flag1=1;
      }
       sum[0]++;
      if(num_max==k) sum[1]++;
      if(kmax<=k) sum[2]++;
      if(!flag) sum[3]++;
      if(!flag) sum[4]++;
  }
  if(n>0)
  {
     for(int i=1;i<=n;i++)
     { 
         num[num_max++]=i;
         f(n-i,k);
     }
  }
  num_max--;
}
int _tmain(int argc, _TCHAR* argv[])
{
    int n,k;
    scanf("%d %d",&n,&k);
    f(n,k);
    for(int i=0;i<5;i++)
        printf("%d\n",sum[i]);
    return 0;
}
评论人: 郑凡群0821  发布时间: 2012-3-29 21:47:56

#include "stdio.h"
#define N 100
int a[N],b[N],c[N],d[N],e[N];
int t=0,total=0,count=0;
int n,p=0;
int dif()
{
    int i,j;
    for(i=0;i<t-1;i++)
        for(j=i+1;j<t;j++)
            if(e[i]==e[j]) return 0;
    return 1;
}

void fun()
{
    t=0;
    total=0;
    count=0;
}
void fun1(int x)
{
    int i,j;
    if(total==n)
    {
        count++;
        printf("%d=",n);
        for(j=0;j<t;j++)
        {
            printf("%d",a[j]);
            if(j<t-1) printf("+");
            else
            {
                if(n-a[0]==t-1) printf("\n");
                else printf(",");
            }
        }
    }
    else 
        for(i=x;i>=1;i--)
            if(i+total<=n)
            {
                a[t++]=i;
                total+=i;
                fun1(i);
            }
    total-=a[t-1];
    t--;
}

void fun2(int x,int m)
{
    int i,j;
    if(total==n)
    {
        if(p==m)
        {
            count++;
            printf("%d=",n);
            for(j=0;j<t;j++)
            {
                printf("%d",b[j]);
                if(j<t-1) printf("+");
                else printf("\n");
            }
        }
    }
    else
        for(i=x;i>=1;i--)
            if(i+total<=n)
            {
                b[t++]=i;
                p++;
                total+=i;
                fun2(i,m);
            }
    total-=b[t-1];
    t--;
    p--;
}

void fun3(int x,int m)
{
    int i,j;
    if(total==n)
    {
        count++;
        printf("%d=",n);
        for(j=0;j<t;j++)
        {
            printf("%d",c[j]);
            if(j<t-1) printf("+");
            else
            {
                if(n-c[0]==t-1) printf("\n");
                else printf(",");
            }
        }
    }
    else
        for(i=m;i>=1;i--)
            if(i+total<=n)
            {
                c[t++]=i;
                total+=i;
                fun3(i,m);
            }
    total-=c[t-1];
    t--;
}

void fun4(int x)
{
    int i,j;
    if(total==n)
    {
        count++;
        printf("%d=",n);
        for(j=0;j<t;j++)
        {
            printf("%d",d[j]);
            if(j<t-1) printf("+");
            else
            {
                if(n-d[0]==t-1) printf("\n");
                else printf(",");
            }
        }
    }
    else
        for(i=x;i>=1;i--)
            if(i+total<=n&&i%2!=0)
            {
                d[t++]=i;
                total+=i;
                fun4(i);
            }
    total-=d[t-1];
    t--;
}

void fun5(int x)
{
    int i,j;
    if(total==n)
    {
        if(dif())
        {
            count++;
             printf("%d=",n);
            for(j=0;j<t;j++)
            {
                printf("%d",e[j]);
                if(j<t-1) printf("+");
                else printf("\n");
            }
        }
    }
    else
        for(i=x;i>=1;i--)
            if(i+total<=n)
            {
                e[t++]=i;
                total+=i;
                fun5(i);
            }
    total-=e[t-1];
    t--;
}
void main()
{
    int k;
    printf("输入是两个整数n和k。(1 <= n <= 50, 1 <= k <= n):");
    scanf("%d%d",&n,&k);
    fun1(n);// 将n划分成若干正整数之和的划分数。
    printf("将%d划分成若干正整数之和的划分数:%d\n\n",n,count);

    fun();
    fun2(n,k);//将n划分成k个正整数之和的划分数。
    printf("\n将%d划分成%d个正整数之和的划分数:%d\n\n",n,k,count);

    fun();
    fun3(n,k);//将n划分成最大数不超过k的划分数。
    printf("将%d划分成最大数不超过%d的划分数:%d\n\n\n\n",n,k,count);

    fun();
    fun4(n);//将n划分成若干奇正整数之和的划分数。
    printf("将%d划分成若干奇正整数之和的划分数:%d\n\n\n",n,count);

    fun();
    fun5(n);//将n划分成若干不同整数之和的划分数。
    printf("将%d划分成若干不同整数之和的划分数:%d\n\n\n",n,count);


}

评论人: KnightZLJ  发布时间: 2009-11-5 0:32:44
#include<iostream.h>
int Func_a(int n,int max)            // 将n划分成最大数不超过max的划分数。 
{
    int counter=0;
    int i;

    if(max<=1)
    {
        return 1;
    }
    else
    {
        for(i=1;i<=max;i++)
        {
            counter+=Func_a(n-i,(i<n-i)?i:(n-i));
        }

        return counter;
    }
}

int Func_b(int n,int k,int max)            //将n划分成k个不大于max的正整数之和的划分数。
{
    int counter=0;
    int min,i;

    min=(int)((n+k-1)/k);
    if(k==1||k==n)
    {
        return 1;
    }
    else
    {
        min=n-(int)(n/k)*(k-1);
        for(i=min;(i<=n-k+1&&i<=max);i++)
        {

            counter+=Func_b(n-i,k-1,i);
        }

        return counter;
    }
}

int Func_c(int n,int max)            //将n划分成若干奇正整数之和的划分数。
{
    int counter=0;
    int i;

    if(max<=1)
    {
        return 1;
    }
    else
    {
        for(i=1;2*i<=max+1;i++)
        {
            counter+=Func_c(n-2*i+1,(i<n-2*i+1)?i:(n-2*i+1));
        }
        return counter;
    }
}




int Func_d(int n,int max)            // 将n划分成若干不同整数之和的划分数。 
{
    int counter=0;
    int i;

    if(max*(max-1)/2<n)
    {
        return 0;
    }else{
        if(max*(max-1)/2==n||n==0)
        {
            return 1;
        }else{
                for(i=1;i<max;i++)
                {
                    counter+=Func_d(n-i,i);
                }
                    return counter;
        }
    }
}




void main()
{
    int n,k;
    cout<<"输入是两个整数n和k。(1 <= n <= 50, 1 <= k <= n)\n";
    cin>>n>>k;
    cout<<Func_a(n,n)<<endl;//第一行: 将n划分成若干正整数之和的划分数。 

    cout<<Func_b(n,k,n-k+1)<<endl;//第二行: 将n划分成k个正整数之和的划分数。 

    cout<<Func_a(n,k)<<endl;//第三行: 将n划分成最大数不超过k的划分数。 


    cout<<Func_c(n,n)<<endl;//第四行: 将n划分成若干奇正整数之和的划分数。 

    cout<<Func_d(n,n)<<endl;//第五行: 将n划分成若干不同整数之和的划分数。 

    cout<<endl;//第六行: 打印一个空行。 

}
评论人: KnightZLJ  发布时间: 2009-11-5 0:32:28
#include<iostream.h>
int Func_a(int n,int max)            // 将n划分成最大数不超过max的划分数。 
{
    int counter=0;
    int i;

    if(max<=1)
    {
        return 1;
    }
    else
    {
        for(i=1;i<=max;i++)
        {
            counter+=Func_a(n-i,(i<n-i)?i:(n-i));
        }

        return counter;
    }
}

int Func_b(int n,int k,int max)            //将n划分成k个不大于max的正整数之和的划分数。
{
    int counter=0;
    int min,i;

    min=(int)((n+k-1)/k);
    if(k==1||k==n)
    {
        return 1;
    }
    else
    {
        min=n-(int)(n/k)*(k-1);
        for(i=min;(i<=n-k+1&&i<=max);i++)
        {

            counter+=Func_b(n-i,k-1,i);
        }

        return counter;
    }
}

int Func_c(int n,int max)            //将n划分成若干奇正整数之和的划分数。
{
    int counter=0;
    int i;

    if(max<=1)
    {
        return 1;
    }
    else
    {
        for(i=1;2*i<=max+1;i++)
        {
            counter+=Func_c(n-2*i+1,(i<n-2*i+1)?i:(n-2*i+1));
        }
        return counter;
    }
}




int Func_d(int n,int max)            // 将n划分成若干不同整数之和的划分数。 
{
    int counter=0;
    int i;

    if(max*(max-1)/2<n)
    {
        return 0;
    }else{
        if(max*(max-1)/2==n||n==0)
        {
            return 1;
        }else{
                for(i=1;i<max;i++)
                {
                    counter+=Func_d(n-i,i);
                }
                    return counter;
        }
    }
}




void main()
{
    int n,k;
    cout<<"输入是两个整数n和k。(1 <= n <= 50, 1 <= k <= n)\n";
    cin>>n>>k;
    cout<<Func_a(n,n)<<endl;//第一行: 将n划分成若干正整数之和的划分数。 

    cout<<Func_b(n,k,n-k+1)<<endl;//第二行: 将n划分成k个正整数之和的划分数。 

    cout<<Func_a(n,k)<<endl;//第三行: 将n划分成最大数不超过k的划分数。 


    cout<<Func_c(n,n)<<endl;//第四行: 将n划分成若干奇正整数之和的划分数。 

    cout<<Func_d(n,n)<<endl;//第五行: 将n划分成若干不同整数之和的划分数。 

    cout<<endl;//第六行: 打印一个空行。 

}
评论人: KnightZLJ  发布时间: 2009-11-5 0:32:13
#include<iostream.h>
int Func_a(int n,int max)            // 将n划分成最大数不超过max的划分数。 
{
    int counter=0;
    int i;

    if(max<=1)
    {
        return 1;
    }
    else
    {
        for(i=1;i<=max;i++)
        {
            counter+=Func_a(n-i,(i<n-i)?i:(n-i));
        }

        return counter;
    }
}

int Func_b(int n,int k,int max)            //将n划分成k个不大于max的正整数之和的划分数。
{
    int counter=0;
    int min,i;

    min=(int)((n+k-1)/k);
    if(k==1||k==n)
    {
        return 1;
    }
    else
    {
        min=n-(int)(n/k)*(k-1);
        for(i=min;(i<=n-k+1&&i<=max);i++)
        {

            counter+=Func_b(n-i,k-1,i);
        }

        return counter;
    }
}

int Func_c(int n,int max)            //将n划分成若干奇正整数之和的划分数。
{
    int counter=0;
    int i;

    if(max<=1)
    {
        return 1;
    }
    else
    {
        for(i=1;2*i<=max+1;i++)
        {
            counter+=Func_c(n-2*i+1,(i<n-2*i+1)?i:(n-2*i+1));
        }
        return counter;
    }
}




int Func_d(int n,int max)            // 将n划分成若干不同整数之和的划分数。 
{
    int counter=0;
    int i;

    if(max*(max-1)/2<n)
    {
        return 0;
    }else{
        if(max*(max-1)/2==n||n==0)
        {
            return 1;
        }else{
                for(i=1;i<max;i++)
                {
                    counter+=Func_d(n-i,i);
                }
                    return counter;
        }
    }
}




void main()
{
    int n,k;
    cout<<"输入是两个整数n和k。(1 <= n <= 50, 1 <= k <= n)\n";
    cin>>n>>k;
    cout<<Func_a(n,n)<<endl;//第一行: 将n划分成若干正整数之和的划分数。 

    cout<<Func_b(n,k,n-k+1)<<endl;//第二行: 将n划分成k个正整数之和的划分数。 

    cout<<Func_a(n,k)<<endl;//第三行: 将n划分成最大数不超过k的划分数。 


    cout<<Func_c(n,n)<<endl;//第四行: 将n划分成若干奇正整数之和的划分数。 

    cout<<Func_d(n,n)<<endl;//第五行: 将n划分成若干不同整数之和的划分数。 

    cout<<endl;//第六行: 打印一个空行。 

}
评论人: KnightZLJ  发布时间: 2009-11-5 0:31:54
#include<iostream.h>
int Func_a(int n,int max)            // 将n划分成最大数不超过max的划分数。 
{
    int counter=0;
    int i;

    if(max<=1)
    {
        return 1;
    }
    else
    {
        for(i=1;i<=max;i++)
        {
            counter+=Func_a(n-i,(i<n-i)?i:(n-i));
        }

        return counter;
    }
}

int Func_b(int n,int k,int max)            //将n划分成k个不大于max的正整数之和的划分数。
{
    int counter=0;
    int min,i;

    min=(int)((n+k-1)/k);
    if(k==1||k==n)
    {
        return 1;
    }
    else
    {
        min=n-(int)(n/k)*(k-1);
        for(i=min;(i<=n-k+1&&i<=max);i++)
        {

            counter+=Func_b(n-i,k-1,i);
        }

        return counter;
    }
}

int Func_c(int n,int max)            //将n划分成若干奇正整数之和的划分数。
{
    int counter=0;
    int i;

    if(max<=1)
    {
        return 1;
    }
    else
    {
        for(i=1;2*i<=max+1;i++)
        {
            counter+=Func_c(n-2*i+1,(i<n-2*i+1)?i:(n-2*i+1));
        }
        return counter;
    }
}




int Func_d(int n,int max)            // 将n划分成若干不同整数之和的划分数。 
{
    int counter=0;
    int i;

    if(max*(max-1)/2<n)
    {
        return 0;
    }else{
        if(max*(max-1)/2==n||n==0)
        {
            return 1;
        }else{
                for(i=1;i<max;i++)
                {
                    counter+=Func_d(n-i,i);
                }
                    return counter;
        }
    }
}




void main()
{
    int n,k;
    cout<<"输入是两个整数n和k。(1 <= n <= 50, 1 <= k <= n)\n";
    cin>>n>>k;
    cout<<Func_a(n,n)<<endl;//第一行: 将n划分成若干正整数之和的划分数。 

    cout<<Func_b(n,k,n-k+1)<<endl;//第二行: 将n划分成k个正整数之和的划分数。 

    cout<<Func_a(n,k)<<endl;//第三行: 将n划分成最大数不超过k的划分数。 


    cout<<Func_c(n,n)<<endl;//第四行: 将n划分成若干奇正整数之和的划分数。 

    cout<<Func_d(n,n)<<endl;//第五行: 将n划分成若干不同整数之和的划分数。 

    cout<<endl;//第六行: 打印一个空行。 

}
评论人: master_zcw  发布时间: 2009-10-20 19:37:12
整数划分问题是将一个正整数n拆成一组数连加并等于n的形式,且这组数中的最大加数不大于n
    6的整数划分为
    最大数  
    6         6
    5        5 + 1
    4         4 + 2, 4 + 1 + 1
    3         3 + 3, 3 + 2 + 1, 3 + 1 + 1 + 1
    2        2 + 2 + 2, 2 + 2 + 1 + 1, 2 + 1 + 1 + 1 + 1
    1         1 + 1 + 1 + 1 + 1 + 1
    
    11种。下面介绍一种通过递归方法得到一个正整数的划分数。
    
    递归函数的声明为 int split(int n, int m);其中n为要划分的正整数,m是划分中的最大加数(当> n时,最大加数为n),
    1 = 1= 1时,split的值为1,可根据上例看出,只有一个划分1  1 + 1 + 1 + 1 + 1 + 1
    可用程序表示为if(== 1 || m == 1) return 1;
    
    2 下面看一看 n的关系。它们有三种关系
    (1) m > n
    在整数划分中实际上最大加数不能大于n,因此在这种情况可以等价为split(n, n);
    可用程序表示为if(> n) return split(n, n);    
    (2) m = n
    这种情况可用递归表示为split(n, m - 1) + 1,从以上例子中可以看出,就是最大加
    数为6和小于6的划分之和
    用程序表示为if(== n) return (split(n, m - 1) + 1);
    (3) m < n
    这是最一般的情况,在划分的大多数时都是这种情况。
    从上例可以看出,设= 4,那split(6, 4)的值是最大加数小于4划分数和整数2的划分数的和。
    因此,split(n, m)可表示为split(n, m - 1) + split(- m, m)
    
    根据以上描述,可得源程序如下:
  

#include <stdio.h>

   int split(int n, int m)
    {
      if(< 1 || m < 1) return 0;
      if(== 1 || m == 1) return 1;
      if(< m) return split(n, n);
      if(== m) return (split(n, m - 1) + 1);
      if(> m) return (split(n, m - 1) + split((- m), m));
   }

int main()
{
      printf("12的划分数: %d", split(12, 12));
    return 0;
}

将正整数划分成连续的正整数之和
15可以划分成4种连续整数相加的形式:
15
7 8
4 5 6
1 2 3 4 5

    首先考虑一般的形式,设n为被划分的正整数,x为划分后最小的整数,如果n有一种划分,那么
结果就是x,如果有两种划分,就是xx x + 1 如果有m种划分,就是 x x x + 1  x x + 1 x + 2 、... x x + 1 x + 2 ... x + m - 1
将每一个结果相加得到一个公式(* x + i * (- 1) / 2) = ni为当前划分后相加的正整数个数。
满足条件的划分就是使x为正整数的所有情况。
如上例,当= 1时,即划分成一个正整数时,= 15 = 2时, x = 7
= 3时,= 4 = 4时,4/9,不是正整数,因此,15不可能划分成4个正整数相加。
= 5时,= 1

    这里还有一个问题,这个i的最大值是多少?不过有一点可以肯定,它一定比n小。我们可以做一个假设,
假设n可以拆成最小值为1的划分,如上例中的1 2 3 4 5。这是n的最大数目的划分。如果不满足这个假设,
那么 i 一定比这个划分中的正整数个数小。因此可以得到这样一个公式* (+ 1) / 2 <= n,即当i满足
这个公式时n才可能被划分。

综合上述,源程序如下

int split1(int n)
{
    int i, j, m = 0, x, t1, t2;
   // 在这里i + 1之所以变为i - 1,是因为i * (i - 1) / 2这个式子在下面多次用到,
  // 为了避免重复计算,因此将这个值计算完后保存在t1中。并且将<= 号变为了<号。
    for(= 1; (t1 = i * (- 1) / 2) < n; i++) 
     {
         t2 = (- t1);
         x =   t2 / i;
        if(<= 0) break;
        if((- t1) % i == 0)
         {
             printf("%d ", x);
            for(= 1; j < i; j++)
                 printf("%d ", x + j);
             printf("\n");
             m++;
         }
     }
    return m;
}
评论人: Guo_tuotuo  发布时间: 2009-5-12 21:53:57
题目比较难呀。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值