Parliament--POJ--1032

Parliament

Time Limit: 1000MS

Memory Limit: 10000K

Total Submissions: 10936

Accepted: 4570

Description

New convocation of The Fool Land's Parliament consists of N delegates. According to the present regulation delegates should be divided into disjoint groups of different sizes and every day each group has to send one delegate to the conciliatory committee. The composition of the conciliatory committee should be different each day. The Parliament works only while this can be accomplished.
You are to write a program that will determine how many delegates should contain each group in order for Parliament to work as long as possible.

Input

The input file contains a single integer N (5<=N<=1000 ).

Output

Write to the output file the sizes of groups that allow the Parliament to work for the maximal possible time. These sizes should be printed on a single line in ascending order and should be separated by spaces.

Sample Input

7

Sample Output

3 4

Source

Northeastern Europe 1998

 

先读懂题意:

题目要求的是对输入的正整数N,要求将N分解成互不相同的正整数的和,使分解出来的这些正整数的乘积最大。

 

解题思路:

先根据数学知识推导出一般式(别想着遍历所有可能的情况):

(以下证明是从网上得来的)

由题意知,这种分解的数目是有限的,因此,最大积存在;

假设最大积的分解为:

N=a1+a2+a3+...+a[t-2]+a[t-1]+a[t] t是分解的数目,a1<a2<a3<...<a[t-2]<a[t-1]<a[t]

下面是该数列的性质及其证明:

1a1>1

如果a1=1,则a1a[t]可以由a[t]+a1=a[t]+1来替代,从而得到更大的积;

 

2)对于所有的i,有a[i+1]-a[i]<= 2

如果存在i使得a[i+1]-a[i]>=3,则a[i]a[i+1]可以替换为a[i]+1a[i+1]-1,从而使乘积更大;

 

3)最多只存在一个i使得a[i+1]-a[i]=2

如果i<ja[i+1]-a[i]=2a[j+1]-a[j]=2,则a[i]a[j+1]可以替换为a[i]+1a[j+1]-1,从而使得乘积更大;

 

4a1<=3

如果a1>=4,则a1a2可以替换为2a1-1a2-1,从而使得乘积更大;

 

5)如果a1=3且存在i满足a[i+1]-a[i]=2,则i一定等于t-1

如果i<t-1,则a[i+2]可以替换为2a[i+2]-2,从而使得乘积更大;

 

将上面5条性质综合一下,得到该数列满足:

11<a1<4

2a[i+1]-a[i] <=2(该序列按升序排序)

3a[i+1]-a[i]=2的情况最多只有一个

 

因此,我们得到最大的乘积的做法就是求出从2开始的最大连续(由上面总结的性质23可知)自然数列之和A,使得A的值不超过N,具体分析如下:

对输入的N,找到k满足:

A=2+3+4+...+(k-1)+k <= N <A+(k+1) = B

假设N=A+p0<=p<k+1),即A+p是最大积的数列

1p=0,则最大积是A

21<=p<=k-1,则最大积是B-{k+1-p},即从数列的最大项i开始,从大到小依次每项加1,知道p=0为止;

3p=k,则最大积是A+p=A+k=A-{2}+{k+2}( =3+4+...+k+( k+2) )

 

代码如下:

#include <iostream>

 

int ans[200];

 

int main()

{

         int N;       //输入的整数

         int sum = 0;   //存储和

         int i;         //全局用到的

         memset(ans,0,sizeof(ans));  //初始化数组

        

         std::cin>>N;

         for(i=2; sum<=N; i++)       //累计和

         {

                   ans[i] = i;

                   sum += i;

         }//此处sum>N,因此下面需要减掉

         i--;    //抵消最后的i++

         sum -= i;

        

         int diff = N - sum; //计算差值

         --i;//抵消倒数第二的i++

         if(diff == i)    //差值等于最后的ans[i]

         {

                   //最大积数列是( =3+4+...+i+( i+2) )

                   for(int j=3; j<=i; j++)         

                   {

                            std::cout<<ans[j]<<" ";    

                   }       

                   std::cout<<i+2;

         }

        

         if(diff>=1 && diff<=(i-1))  //差值1<=diff<=i-1

         {

                   int tmp = i;//为了不修改i

                   //最大积数列是从原始数列(2,3,4,...,i)的最大项开始

                   //从大到小依次每项加1,直到diff=0为止

                   for(int k=diff; k>0; k--)        

                   {

                            ans[tmp--]++;        

                   }

                  

                   int t;

                   for(t=2; t<i; t++)

                   {

                            std::cout<<ans[t]<<" ";    

                  }

                   std::cout<<ans[t];

         }

        

         if(diff == 0)//差值为0,则最大积数列就是原始数列2,3,4,...,i

         {

                   int p;

                   for(p=2; p<i;p++)

                   {

                            std::cout<<ans[p]<<" ";

                   }

                   std::cout<<ans[p];

         }

        

         system("pause");

         return 0;

}

posted on 2010-05-29 13:20  android开发实例  阅读(204)  评论(0编辑  收藏  举报

导航