整数划分问题之最大乘积

Posted 若有恒,何必三更起五更眠;最无益,莫过一日曝十日寒。

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了整数划分问题之最大乘积相关的知识,希望对你有一定的参考价值。

题目链接:

https://www.nowcoder.com/acm/contest/110/A

分析:

(1)对于任意大于等于4的正整数m, 存在一个划分m = m1+m2, 使 m1*m2 >= m证: 令m1 = int(m/2), 则 m1 >= 2 , m2 = m-m1; 那么m2 > 2,并且 m2 >= m/2 >= m1;    m1*m2 >= 2*m2 >= m; 证毕;
该证明简单的来说就是:对于一个大于等于4的正整数m,存在一个2块划分的因子,这两个因子的乘积总是不小于原数m本身。
(2)由(1)知此数最终可以分解为 2^r * 3^s。现证明 r <= 2;
证:若r > 2, 则至少有3个因子为2, 而2*2*2 < 3*3;
所以可以将3个为2的因子,换为两个因子3;积更大;证毕。
综合(1),(2),则有:任何大于4的因子都可以有更好的分解, 而4可以分解为2*2。
所以:此数应该分解为 2^k1 * 3^k2。而且可以证明 k1>=0 并且 k1 <= 2,因此:
     A.当n = 3*r 时, 分解为 3^r
     B.当n = 3*r+1时, 分解为 3^(r-1)*2*2
     C.当n = 3*r+2时, 分解为 3^r*2

参考至他人博客:https://www.cnblogs.com/xiaoxian1369/archive/2011/09/12/2174212.html

代码如下:

#include<bits/stdc++.h>
using namespace std;
long long f(int n)
{
    long long s=1;
    for(int i=1; i<=n; i++)
    {
        s=s*3;
        s=s%2000000000000000003;
    }
    return s;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int s;
        scanf("%d",&s);
        if(s<=4)
        {
            printf("%d\\n",s);
        }
        else
        {
            long long x;
            int r=s/3;
            if(s%3==0)
            {
                x=f(r);
            }
            else if(s%3==1)
            {
                x=f(r-1)*2*2;
            }
            else if(s%3==2)
            {
                x=f(r)*2;
            }
            printf("%lld\\n",x%2000000000000000003);
        }
    }
    return 0;
}

注意:求3的次方的函数中每次都要取模,不然会wa

 

以上是关于整数划分问题之最大乘积的主要内容,如果未能解决你的问题,请参考以下文章

求划分因子乘积最大的一个划分及此乘积

BZOJ1263 [SCOI2006]整数划分

NYOJ 746 - 正整数n划分为m段,求m段的最大乘积 区间DP

牛客网练习赛18 A 数论/整数划分得到乘积最大/快速乘

BZOJ 1263 整数划分(数学+高精度)

BZOJ1263 [SCOI2006]整数划分 高精度