题目描述
经过第一轮的游戏,不少同学将会获得圣诞特别礼物,但这时细心的数学课代表发现了一个问题:留下来的人太多而使礼物数量可能不够,为此,加试了一道数学题:将一个正整数n分解成若干个互不相等的正整数的和,使得这些数的乘积最大,当主持人报出一个n后,请你立即将这个最大值报出来,现请你帮你的好友编一个程序来解决这个问题。
输入格式
输入中只有1个数n(其中1<=n<=1000)。
输出格式
输出中也是一个数,是乘积的最大值。
样例输入
7样例输出
12
此题时将整数M划分成N个不同整数 使N个整数乘积最大 (Wikioi 2612 / RQNOJ 269 / TYVJ 1260)
首先我们不会分解出1
将M划分成1和(M-1) 乘积不会比M大
1.对于小于4的数 无法将它划分出乘积大于自身的数 所以就不划分
2.当M=4时 2+2=2*2 我们可以划分也可以不划分 为了方便 将它划分成2+2
3.当M>4时 保证不重复和不分解出1 分解出的数越多越好
M>4时 可以分解成2个整数乘积大于M
为了分解更多的数
1.可以将M分解成2+3+...+k一直到和大于等于M
若和=M 则此方案为最佳
否则必须删掉一个数
当比M大1时 删掉2 并将(k-1)变成k
当比M大w(w!=1)时 删掉w
2.分解成2+3+...+k<=M使得再加上k+1时大于M
则对于差w 将w分成w个1 从大到小加到分解的数上
若w>k-1 则加完一边后再继续从大到小加1
如分解6
2+3<6<2+3+4
2+3+4-6=3
将3分成3个1
加到3 2 上 还剩一个1
再加到4 3中的3上
由大到小的顺序 是为了保证不相同
代码如下
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int s[11111];
int ans[1111];
int m,a,b,c,n;
void print(int ans[1111])
{
int a;
for(a=1000;a>1;a--)
if(ans[a])break;
while(a)
{
cout<<ans[a];
a--;
}
}
void jinwei(int ans[1111])
{
int i;
for(int i=1;i<=1000;i++)
if(ans[i]>=10)
{
ans[i+1]=ans[i+1]+ans[i]/10;
ans[i]%=10;
}
}
void calc()
{
int a,b;
ans[1]=1;
for(a=1;a<=n;a++)
{
for(b=1;b<=500;b++)
ans[b]=ans[b]*s[a];
jinwei(ans);
}
}
int main()
{
cin>>m;
for(a=1;m>s[a-1];a++)
{
s[a]=min(a+1,m);
m-=s[a];
if(m<=s[a])break;
}
n=a;
while(m)
{
for(a=n;a>=1;a--)
{
s[a]++;
m--;
if(m<=0)break;
}
}
calc();
print(ans);
return 0;
}
对于可相同的整数划分(VIJOS 1033)
将整数M划分成N个整数 使N个整数乘积最大(Wikioi 3179)
将M划分成1和(M-1) 乘积不会比M大 故不分解出1
因此
1.对于小于4的数 无法将它划分出乘积大于自身的数 所以就不划分
2.当M=4时 2+2=2*2 我们可以划分也可以不划分 为了方便 将它划分成2+2
3.当M>4时 可证明M分解成若干整数的和 他们的积大于M
考虑分解成2个数的情况
当M为偶数时 (M/2)^2>M 解得M>4
当M为奇数时 ((M+1)/2)*((M-1)/2)>M 解得M>2*5^(1/2)
因此M>4时 可以分解成2个整数乘积大于M 需要将它分解
M>4时 令M=x+(M-x)
考虑y=x*(M-x) y表示数乘积比M大的值
y为二次函数 开口向下 在M/2时取到最大值 在(0,M/2)单调递增 在(M/2,M)单调递减
所以M为偶数时 分解成M/2+M/2
M为奇数时 分解成(M+1)/2+(M-1)/2
然后对分解后的数也尝试考虑1.2.3
这样做后 发现最后分解的数都为2和3
由于2*2*2<3*3而2+2+2=3+3
所以每分解成3个2 我们将它变成2个3
这样就可以求出最大的乘积
#include<iostream>
#include<cstdio>
using namespace std;
int m,a,b,z[1011];
void print()
{
int a;
for(a=1000;a>1;a--)if(z[a])break;
while(a)
{
cout<<z[a];a--;
}
cout<<'\n';
}
void jinwei()
{
for(int a=1;a<=1000;a++)
if(z[a]>=10)
{
z[a+1]=z[a+1]+z[a]/10;
z[a]%=10;
}
}
void calc()
{
z[1]=1;
while(b)
{
z[1]*=2;
b--;
}
while(a)
{
for(int k=1;k<=1000;k++)z[k]*=3;
jinwei();
a--;
}
print();
}
int main()
{
cin>>m;
if(m<=4)
{
cout<<m<<'\n';
return 0;
}
while(m%3!=0)
{
b++;
m-=2;
}
a=m/3;
calc();
return 0;
}