zoukankan      html  css  js  c++  java
  • 最大乘积

    D14635. 最大乘积

    时间限制:1.0s 内存限制:256.0MB
    输入文件名:test.in 输出文件名:test.out
    问题描述
      一个正整数一般可以分为几个互不相同的自然数的和,如3=1+2,4=1+3,5=1+4=2+3,6=1+5=2+4,…。
      现在你的任务是将指定的正整数n分解成若干个互不相同的自然数的和,且使这些自然数的乘积最大。
    输入格式
      只一个正整数n,(3≤n≤10000)。
    输出格式
      第一行是分解方案,相邻的数之间用一个空格分开,并且按由小到大的顺序。
      第二行是最大的乘积。
    样例输入
    10
    样例输出
    2 3 5
    30

    思路:
    夏令营做过的题。
    当时dfs暴力苟得30。
    贪心策略:将一个正整数N从2开始拆分,将其拆分为2+3+4+……..+Ak,此时存在余数res是前已存在过的结果。将其平均分配给前k项,注意要优先考虑最后,如果先分配给靠前数会产生重复现象。最后乘出结果。
    实测要求高精度。重载运算符解决。
    证明:设有一数A=2S,可拆分为s-1+s+1,此时乘积mult1 = s^2-1。亦可拆分为s-2+s+2,mult2 = s^2 – 4 < mult1。由此可得出拆分的两项差值越小乘积越大。而以上拆分的递增数列满足条件。而将余数平均分配尽力维护了差值更小。以上策略正确。

    Code:

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    
    struct bign{
    	int len, s[2010];
    	bign () {memset(s, 0, sizeof(s)), len = 1;} 
    	bign (int num){ *this = num;} 
    	bign (char *num) {*this = num;} 
    	bign (const char *num){ *this = num;} 
    	bign operator = (int num) {
    		char s[2010];
    		sprintf(s, "%d", num);
    		*this = s;
    		return *this;
    	}
    	string str() const {
    		string res = "";
    		for (int i = 0; i < len; i++)
    			res = (char) (s[i] + '0') + res;
    			if (res == "") res = "0";
    			return res;
    	}
    	void clear(){ while(len > 1 && !s[len - 1]) len --;}
    	bign operator = (const char *num) {
    		len = strlen(num);
    		for (int i = 0; i < len; i++)
    			s[i] = num[len - i - 1] - '0';
    			return *this;
    	}
    	bign operator + (const bign &b) const {
    		bign c = *this;
    		int i = 0;
    		for (int i = 0; i < b.len; i++) {
    			c.s[i] += b.s[i];
    			if (c.s[i] > 9) c.s[i] %= 10, c.s[i + 1] ++;
    		}
    		while (c.s[i] > 9) c.s[i++] %= 10, c.s[i]++;
    		c.len = max(len, b.len);
    		if (c.s[i] && c.len <= i) c.len = i + 1;
    		return c;
    	}
    	bign operator - (const bign &b) const {
    		bign c = *this;
    		int i = 0;
    		for (int i = 0; i < b.len; ++i) {
    			c.s[i] -= b.s[i];
    			if (c.s[i] < 0) c.s[i] += 10, c.s[i + 1] --;
    		}
    		while (c.s[i] < 0) c.s[i++] += 10, c.s[i] --;
    		c.clear();
    		return c;
    	}
    	bign operator * (const bign &b) const {
    		int i, j;
    		bign c;
    		c.len = len + b.len;
    		for (int j = 0; j < b.len; j++)
    			for (int i = 0; i < len; i++)
    				c.s[i + j] += s[i] * b.s[j];
    		for (int i = 0; i < c.len - 1; i++){
    			c.s[i + 1] += c.s[i] / 10;
    			c.s[i] %= 10;
    		}
    		c.clear();
    		return c;
    	}
    	bign operator / (const bign &b) const {
    		bign c = *this, a = 0;
    		int i, j;
    		for (i = len - 1; i >= 0; i --) {
    			a = a * 10 + s[i];
    			for (j = 0; j < 10; j++) 
    				if (a < b * (j + 1)) break;
    			c.s[i] = j;
    			a = a - b * j;
    		}
    		c.clear();
    		return c;
    	}
    	bign operator % (const bign &b) const {
    		int i, j;
    		bign c = 0;
    		for (int i = len - 1; i >= 0; i--) {
    			c = c * 10 + s[i];
    			for (int i = len - 1; i >= 0; --i){
    				if (c < b * (j + 1)) break;
    				c = c - b * j;
    			}
    		}
    		return c;
    	}
    	bign operator += (const bign &b){
    		*this = *this + b;
    		return *this;
    	}
    	bool operator < (const bign &b) const{
    		if (len != b.len) return len < b.len;
    		for (int i = len - 1; i >= 0; i--)
    			if (s[i] != b.s[i]) return s[i] < b.s[i];
    		return false;
    	}
    	bool operator > (const bign &b) const {return b < *this;}
    	bool operator <= (const bign &b) const {return !(b < *this);}
    	bool operator >= (const bign &b) const {return !(*this < b);}
    	bool operator == (const bign &b) const {return !(b < *this) && !(*this < b);}
    	bool operator != (const bign &b) const {return (b < *this) || (*this < b);}
    };
    
    istream& operator >> (istream &in, bign &x) {
    	string s;
    	in >> s;
    	x = s.c_str();
    	return in;
    }
    
    ostream& operator << (ostream &out, bign &x){
    	out << x.str();
    	return out;
    }
    //以上是运算符重载。
    
    ll n, cnt = 0, num[100010];
    bign ans = 1;
    
    int main(){
    	freopen("test.in","r",stdin);
    	freopen("test.out","w",stdout);
    	cin >> n;
    	if (n <= 4){
    		cout << 1 << " " << n - 1 << endl;
    		cout << n - 1 << endl;
    		return 0;
    	}//当n<=4时存在特殊情况,其只可拆分为1+n-1。
    	ll h = 0;
    	for (int i = 2; h <= n; i++){
    		num[++cnt] = i;
    		h += i;
    	}
    	h -= num[cnt];
    	int res = n - h;
    	for (int i = 1; i < cnt && res; i++) 
    num[cnt - i] ++, res --;//平均分配。
    	if (res) num[cnt - 1] = num[cnt - 1] + res;
    	for (int i = 1; i < cnt; i++)
    		cout << num[i] << " ";
    	cout << endl;
    	for (int i = 1; i < cnt; i++)
    		ans = ans * num[i];
    	cout << ans << endl;
    	return 0;
    }
    
  • 相关阅读:
    Elasticsearch-PHP 索引操作2
    Elasticsearch-PHP 索引操作
    Linux系统编程1_C标准函数库和系统调用
    Git命令_git commit
    Git命令_git log
    Linux27_配置samba
    计算机网络12_整理
    理解操作系统8——字符设备与块设备
    网站开发基础知识3_会话和cookie
    网站开发基础知识2_前后端分离
  • 原文地址:https://www.cnblogs.com/sun915/p/9501487.html
Copyright © 2011-2022 走看看