BZOJ1263 [SCOI2006]整数划分 高精度

时间:2023-03-08 18:05:10

欢迎访问~原文出处——博客园-zhouzhendong

去博客园看该题解


题目传送门 - BZOJ1263


题意概括

  将n写成若干个正整数之和,并且使这些正整数的乘积最大。 例如,n=13,则当n表示为4+3+3+3(或2+2+3+3+3)时,乘积=108为最大。


题解

  设F(n)为n的乘积ans。

  那么有:

  F(n) = 3 * F(n - 3)  n>4

  F(n) = n                 n<=4

  然后压位高精度跑一跑就可以了。

  证明我想大家都会吧。

  呵呵的我一开始输出了后100位,差错半天……


代码

#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long LL;
int n,x;
struct BigInt{
static const int MaxLen=600;
static const LL mod=1e9;
int d;
LL v[MaxLen];
void Print(){
printf("%lld",v[d]);
for (int i=d-1;i>0;i--)
printf("%09lld",v[i]);
}
void operator = (int x){
memset(v,0,sizeof v);
d=1,v[1]=x;
}
BigInt operator * (int x){
BigInt res=*this;
for (int i=1;i<=res.d;i++)
res.v[i]*=x;
for (int i=1;i<=res.d;i++)
res.v[i+1]+=res.v[i]/mod,res.v[i]%=mod;
while (res.v[res.d+1]>0)
res.d++,res.v[res.d+1]=res.v[res.d]/mod,res.v[res.d]%=mod;
return res;
}
void operator *= (int x){
*this=*this*x;
}
}Ans;
int digit(LL x){
int ans=0;
while (x)
x/=10,ans++;
return ans;
}
int Find_Digit(LL x,int y){
y--;
while (y--)
x/=10;
return x%10;
}
int main(){
scanf("%d",&n);
x=n%3;
if (x!=2)
x+=3;
n=(n-x)/3;
Ans=x;
for (int i=1;i<=n;i++)
Ans*=3;
printf("%d\n",(Ans.d-1)*9+(int)(log((double)Ans.v[Ans.d])/log(10)+1));
if (Ans.d>11){
int cnt=digit(Ans.v[Ans.d]),m=100-cnt;
printf("%lld",Ans.v[Ans.d]);
int i,j;
for (i=Ans.d-1;m>9;i--,m-=9)
printf("%09lld",Ans.v[i]);
for (j=m;j>=1;j--)
printf("%d",Find_Digit(Ans.v[i],j+9-m));
}
else
Ans.Print();
return 0;
}