整数划分
时间限制: 1 Sec 内存限制: 128 MB
题目描述
读入一个正整数n。要求将n写成若干个正整数之和,并且使这些正整数的乘积最
大。例如,n=13,则当n表示为4+3+3+3(或2+2+3+3+3)时,乘积=108为最大。
输入
一个整数,n。
输出
第1行输出一个整数,为最大乘积的位数。第2行输出最大乘积的前100位,如果
不足100位,则按实际位数输出最大乘积。(提示:在给定的范围内,最大乘积的
位数不超过5000位)。
样例输入
13
样例输出
3
108
提示
【数据范围】
10 ≤ n ≤ 31000
分析
结论是,尽量把这个数拆成若干个3的和,特殊的是,如果拆到最后还剩4, 不要拆成1+3而是拆成2+2。
证明如下:
假
设
n
=
x
1
+
x
2
+
⋯
+
x
k
,
现
在
要
求
(
x
1
∗
x
2
∗
⋯
∗
x
k
)
m
a
x
假设n=x_1+x_2+\cdots+x_k,现在要求(x_1*x_2*\cdots*x_k)_{max}
假设n=x1+x2+⋯+xk,现在要求(x1∗x2∗⋯∗xk)max。
如
果
其
中
某
个
x
i
≥
4
,
那
么
x
i
可
以
继
续
划
分
为
x
i
=
2
+
(
x
i
−
2
)
,
而
(
x
i
−
2
)
∗
2
=
2
x
i
−
4
≥
x
i
,
所
以
x
i
可
以
继
续
划
分
,
故
没
有
x
i
≥
4
。
如果其中某个x_i \ge 4,那么x_i可以继续划分为x_i=2+(x_i-2),而(x_i-2)*2=2x_i-4\ge x_i,所以x_i可以继续划分,故没有x_i\ge 4。
如果其中某个xi≥4,那么xi可以继续划分为xi=2+(xi−2),而(xi−2)∗2=2xi−4≥xi,所以xi可以继续划分,故没有xi≥4。
接
下
来
,
如
果
某
个
x
i
=
1
,
那
对
乘
积
没
有
贡
献
,
就
是
浪
费
了
一
个
数
。
由
此
我
们
推
断
所
有
的
x
都
是
2
或
者
3
。
接下来,如果某个x_i=1,那对乘积没有贡献,就是浪费了一个数。由此我们推断所有的x都是2或者3。
接下来,如果某个xi=1,那对乘积没有贡献,就是浪费了一个数。由此我们推断所有的x都是2或者3。
下
面
证
明
2
的
数
量
不
超
过
2
个
。
如
果
有
三
个
及
以
上
的
2
,
则
由
2
∗
2
∗
2
<
3
∗
3
得
,
尽
量
拆
3
是
更
好
的
选
择
。
下面证明2的数量不超过2个。如果有三个及以上的2,则由2*2*2<3*3得,尽量拆3是更好的选择。
下面证明2的数量不超过2个。如果有三个及以上的2,则由2∗2∗2<3∗3得,尽量拆3是更好的选择。
最
后
,
考
虑
到
还
剩
4
的
特
殊
情
况
。
搞
定
。
最后,考虑到还剩4的特殊情况。搞定。
最后,考虑到还剩4的特殊情况。搞定。
考试的时候看成了输出后一百位。
不晓得得了多少分,反正不会很高就是了。
代码
#include<cstdio>
#include<algorithm>
using namespace std;
int n,arr[102030]={0,1},weis=1;
inline void times(int x)
{
for(int i=1;i<=weis;i++) arr[i]*=x;
for(int i=1;i<=weis;i++) arr[i+1]+=arr[i]/10,arr[i]%=10;
if(arr[weis+1]) weis++;
}
int main()
{
scanf("%d",&n);
if(n==1) return puts("1"),0;
int T=n/3,las=n%3;
if(las<=1) T--,las+=3;
while(T--) times(3); times(las);
printf("%d\n",weis);
for(int i=weis;i>=max(1,weis-99);i--) printf("%d",arr[i]);
puts("");
}