P1249 最大乘积

// Problem: P1249 最大乘积
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1249
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// User: Pannnn

#include <bits/stdc++.h>

using namespace std;

/*
    把n分拆成若干个互不相等的自然数的和的分法只有有限种,因而一定存在一种分法,使得这些自然数的乘积最大。
    因1作因数,则显然乘积不会最大。把n分拆成若干个互不相等的自然数的和,因数个数越多,乘积越大。
    为了使因数个数尽可能多,把n分成2+3+...+k直到满足2+3+...+k <= n且2+3+...+k+(k+1)大于n,
    令s = 2+3+...+k,一共k-1个数
    若s < n,则还需要分配n - s。
    如果能把数分到更小的数上,那么乘积更大,但不允许数重复,需要从大数开始向前,依次分配1
    
    如 s = 2 + 3 + 4 + 5 + 6 + 7
    例如 n - s等于1
       分配后:2 + 3 + 4 + 5 + 6 + 8
    例如n - s等于3
       分配后:2 + 3 + 4 + 6 + 7 + 8
       
    即从某个位置开始,全部加1
    
    可视为从2 + 3 + ... + k + (k + 1)使得s > n后删去某个数
    特殊情况,若和比n大1,则因数个数至少减少一个,为了使乘积最大,去掉最小的2,并将最后一个数加上1
    否则,去掉等于s-n的那个数
    此时乘法最大(去掉可以使其值变为1,不影响结果)
*/

vector<int> mul(vector<int> a, int b) {
    vector<int> res;
    int pre = 0;
    for (int i = 0; i < a.size(); ++i) {
        pre += a[i] * b;
        res.push_back(pre % 10);
        pre /= 10;
    }
    
    while (pre) {
        res.push_back(pre % 10);
        pre /= 10;
    }
    return res;
}

int main() {
    vector<int> resQue;
    int n;
    cin >> n;
    
    int sum = 0;
    int tmp = 2;
    while (sum <= n) {
        sum += tmp;
        resQue.push_back(tmp);
        ++tmp;
    }
    
    if (sum - n == 1) {
        resQue.front() = 1;
        ++resQue.back();
    } else {
        resQue[sum - n - 2] = 1;
    }
    
    vector<int> mulRes(1, 1);
    for (int i = 0; i < resQue.size(); ++i) {
        if (resQue[i] == 1) { continue; }
        cout << resQue[i] << " ";
        mulRes = mul(mulRes, resQue[i]);
    }
    cout << endl;
    
    for (int i = mulRes.size() - 1; i >= 0; --i) {
        cout << mulRes[i];
    }
    cout << endl;
    return 0;
}
posted @ 2022-01-26 17:06  Pannnn  阅读(188)  评论(0)    收藏  举报
-->