话说这是我第一篇数论方面的题解啊……如有不足,请大佬们给予指导
题目描述
题意分析
给出一个数 n n n,把这个数分解成很多个正整数的和,然后把分解出来的这些数撑起来,求最大的积
数学分析
按照那句老话,数学上来先打表,所以
- 排除(浪费)
- 最大积 = 2 \ =2 =2
- 最大积 = 3 \ =3 =3
- 最大积 = 2 ∗ 2 = 4 \ =2*2=4 =2∗2=4
- 最大积 = 2 ∗ 3 = 6 \ =2*3=6 =2∗3=6
- 最大积 = 3 ∗ 3 = 9 \ =3*3=9 =3∗3=9
- 最大积 = 2 ∗ 2 ∗ 3 = 12 \ =2*2*3=12 =2∗2∗3=12
- 最大积
=
2
∗
3
∗
3
=
18
\ =2*3*3=18
=2∗3∗3=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 < 3 ∗ 3 2*2*2<3*3 2∗2∗2<3∗3,所以应该多选3。
所以,就可以针对 n n n除以3的余数进行分类讨论。特别地,如果余数为1,应该少分一个3,转化成 2 ∗ 2 2*2 2∗2。
最后,如果你不会高乘高,请练习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]);
}