记录一下从题解里学到的知识点 以下是引用
本题要先用简单的数论和贪心找到最优解的组成方法,再用高精度乘法求积。
以2004为例,由于把2004分拆成若干个互不相等的自然数的和的分法只有有限种,因而一定存在一种分法,使得这些自然数的乘积最大。
若1作因数,则显然乘积不会最大。把2004分拆成若干个互不相等的自然数的和,因数个数越多,乘积越大。为了使因数个数尽可能地多,我们把2004分成2+3…+n直到和大于等于2004。
若和比2004大1,则因数个数至少减少1个,为了使乘积最大,应去掉最小的2,并将最后一个数(最大)加上1。
若和比2004大k(k≠1),则去掉等于k的那个数,便可使乘积最大。
例如15:s=2+3+4+5+6刚好大于15,s-15=5,所以把5去掉。
又例如13:s=2+3+4+5刚好大于13,s-13=1,所以去掉2,并把5加1,即3 4 6。
然后没啥好说的了,直接上代码
#include<iostream>
using namespace std;
int a[5005],t=1,result[5005],lenr=5005;
void fenjie(int n)
{
if(n==3||n==4)
{
a[t++]=n;
return ;
}
int s=0;
for(int i=2;i<=n;i++)
{
if(s+i<=n)
{
a[t++]=i;
s+=i;
}
else
{
a[t++]=i;
s=s+i-n;
if(s==1)
{
a[1]=0;
a[t-1]++;
}
else
{
for(int j=1;j<=i;j++)
{
if(a[j]==s)
{
a[j]=0;
break;
}
}
}
break;
}
}
}
void xf()
{
for(int i=1;i<=t;i++)
{
if(!a[i])continue;
int cur=0;
for(int j=1;j<=lenr;j++)
{
cur=result[j]*a[i]+cur/10;
result[j]=cur%10;
}
}
while(result[lenr]==0&&lenr>1)lenr--;
}
int main()
{
int n;
cin>>n;
fenjie(n);
result[1]=1;t--;
xf();
for(int i=1;i<=t;i++)
if(a[i])
cout<<a[i]<<' ';
cout<<endl;
for(int i=lenr;i>=1;i--)
cout<<result[i];
cout<<endl;
return 0;
}
版权声明:本文为Lil_oat原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。