BZOJ1263 [SCOI2006]整数划分 高精度

欢迎访问~原文出处——博客园-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;
}

  

 

posted @ 2017-08-19 22:47  zzd233  阅读(441)  评论(0编辑  收藏  举报