【C++】LG P4157 整数划分


数论有一部分的总括

话说这是我第一篇数论方面的题解啊……如有不足,请大佬们给予指导

题目描述

同样的小网址

题意分析

给出一个数 n n n,把这个数分解成很多个正整数的和,然后把分解出来的这些数撑起来,求最大的积

数学分析

按照那句老话,数学上来先打表,所以

  1. 排除(浪费)
  2. 最大积   = 2 \ =2  =2
  3. 最大积   = 3 \ =3  =3
  4. 最大积   = 2 ∗ 2 = 4 \ =2*2=4  =22=4
  5. 最大积   = 2 ∗ 3 = 6 \ =2*3=6  =23=6
  6. 最大积   = 3 ∗ 3 = 9 \ =3*3=9  =33=9
  7. 最大积   = 2 ∗ 2 ∗ 3 = 12 \ =2*2*3=12  =223=12
  8. 最大积   = 2 ∗ 3 ∗ 3 = 18 \ =2*3*3=18  =233=18
    ………………

诶?列举了这么多(哪里多了),都是分解成2和3?那是不是就可以按照这个规律,全部都分解成2和3呢?
答案是肯定的。

为什么呢?因为这是一个结论题。

尽可能将这个数分成两半来解决。如果是偶数,那么分成 n / 2 + n / 2 n/2+n/2 n/2+n/2;如果是奇数,那么分成 n / 2 + ( n / 2 + 1 ) n/2+(n/2+1) n/2+(n/2+1)。这样分下来,一定会分到2和3,也就是很小的奇数和偶数。

为什么不分到1呢?上面已经很好的用一个词说明了——浪费。减了一个1,结果一点变化也没有

再来说,2和3,优先分哪个?

因为 2 + 2 + 2 = 3 + 3 2+2+2=3+3 2+2+2=3+3,而此时 2 ∗ 2 ∗ 2 &lt; 3 ∗ 3 2*2*2&lt;3*3 222<33,所以应该多选3。

所以,就可以针对 n n n除以3的余数进行分类讨论。特别地,如果余数为1,应该少分一个3,转化成 2 ∗ 2 2*2 22

最后,如果你不会高乘高,请练习Python右转这道题

代码

我的模板写真的Very Ugly,而且太蒟了,还不会FFT,如果您觉得不好看,敬请谅解

#include<map>
#include<set>
#include<list>
#include<queue>
#include<deque>
#include<stack>
#include<ctime>
#include<cmath>
#include<vector>
#include<bitset>
#include<cstdio>
#include<cctype>
#include<string>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<iomanip>
#include<iostream>
#include<algorithm>
using namespace std;
#define reg register
inline bool OpenFile() {
    freopen("divide.in","r",stdin);
    freopen("divide.out","w",stdout);
    return 1;
}
//bool _Open=OpenFile();
template <typename T>
inline T read() {
    T a=0; char c=getchar(),f=1;
    while(c<'0'||c>'9') {
        if(c=='-') f=-f;
        if(c==-1) return c;
        c=getchar();
    }
    while(c>='0'&&c<='9') a=(a<<1)+(a<<3)+(c^48),c=getchar();
    return a*f;
}
template <class T>
inline int write(T x) {
    if(x<0) x=(~x)+1, putchar('-');
    if(x/10) write(x/10);
    return putchar(x%10|48);
}
template <class T>
inline int write(T x,char c) {
    return write(x)&&putchar(c);
}
template <class T>
inline T Max(T a,T b) { return a>b?a:b; }
template <class T>
inline T Min(T a,T b) { return a<b?a:b; }
template <class T>
inline T Abs(T a) { return a<0?-a:a; }
struct bigint{
    int a[10001];
    inline bigint& operator = (const char *s) {
        memset(a,0,sizeof a);
        int len=strlen(s);
        a[0]=len;
        for(reg int i=0,j;(j=len-i)&&i<len;i++)
            a[j]=s[i]^48;
        return *this;
    }
    inline bigint& operator = (const int &a) {
        char s[5001];
        sprintf(s,"%d",a);
        return *this=s;
    }
    inline bigint() {}
    inline bigint(const char *s) { *this=s; }
    inline bigint(const int &a) { *this=a; }
    inline void input() {
        char s[5001];
        scanf("%s",s); *this=s;
    }
    inline void output() {
        for(reg int i=a[0];i>=1;i--) write(a[i]);
    }
    inline bigint operator * (const bigint & b) {
        bigint c; c=0;
        c.a[0]=a[0]+b.a[0];
        for(reg int i=1;i<=a[0];i++)
            for(reg int j=1;j<=b.a[0];j++) {
                c.a[i+j-1]+=a[i]*b.a[j];
                c.a[i+j]+=c.a[i+j-1]/10;
                c.a[i+j-1]%=10;
            }
        while(!c.a[c.a[0]]) c.a[0]--;
        if(!c.a[0]) c.a[0]=1;
        return c;
    }
}ans;
inline bigint piow(bigint a,int b) {//反正只是2和3相乘起来,3的幂直接快速幂解决
    bigint ans=1;
    while(b) {
        if(b&1) ans=ans*a;
        a=a*a;
        b>>=1;
    }
    return ans;
}
int main() {
    int n=read<int>();
    int t=n/3,t1=n%3;
    if(t1==0) ans=piow(3,t);
    else if(t1==1) ans=piow(3,t-1)*4;
    else ans=piow(3,t)*2;
    write(ans.a[0],'\n');
    for(reg int i=ans.a[0],j=1;i>=1&&j<=100;i--,j++)//输出前一百位
        write(ans.a[i]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值