求把某数分拆成几个自然数的和,求这些数的最大乘积的公式

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了求把某数分拆成几个自然数的和,求这些数的最大乘积的公式相关的知识,希望对你有一定的参考价值。

快点

最大积为2^m+3^n的形式

证明如下:
设正整数为k,Xi(i=1,2,……n〈=k)
并且Xi的和为k 积为X1*X2*……*Xn
1)
任意的非最大的Xi=1,否则不妨设X1=1,并将X1与另一个数相加,如以1+X2取代1与X2这两个数易知(1)不变(和不变),而积中因子“1*X2”代之以“1+X2”,显然有
1*X2*X3****Xn <(1+X2)*X3****Xn
2)
任意的非最大的Xi <=4,否则不妨设X1> 4,此时可令
X1=2+a(a> 2)
易知(1)不变,而积中因子X1以
2*a=2(X1-2)=2X1-4=X1+(X1-4)> X1
代替,显然:
(2+a)*X2*X3***Xn <2*a*X2*X3****Xn
即积增大
由1),2)知最大的积因子只能在2,3,4中选,而4=2+2=2*2,故4可看作两个2
因而Xi只能在2,3中选取,最大积为2^m+3^n的形式,m,n满足 2m+3n=k
因为三个2可以用两个3代替,和不变积增大(2*2*2 <3*3)故2的个数m=1或m=2
参考技术A 尽量拆成3和2的和,其中3要尽量多,不要出现1
以16为例
16=3+3+3+3+2+2
所以乘积最大为2×2×3×3×3×3=324
15=3+3+3+3+3
14=3+3+3+3+2
13=3+3+3+2+2本回答被提问者采纳
参考技术B 设某数X,则(1) X/3=Y ....0 最大乘积: 3^Y
(2) X/3=Y ....1 最大乘积:2^2 *3^(Y-1)
(3) X/3=Y ....2 最大乘积:2 *3^Y

最大乘积

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;
}



















以上是关于求把某数分拆成几个自然数的和,求这些数的最大乘积的公式的主要内容,如果未能解决你的问题,请参考以下文章

最大乘积

关于gcd函数解最大公约数

D. Taxes分拆素数和

(java) 将一个自然数分解成几个质数的连乘积形式 举例 input:60 output:2*2*3*5

几个数字求乘积最大或者最小,思路是啥

几个数字求乘积最大或者最小,思路是啥