整数划分
来源:互联网 发布:360软件管理 编辑:程序博客网 时间:2024/05/16 14:42
题目描述
经过第一轮的游戏,不少同学将会获得圣诞特别礼物,但这时细心的数学课代表发现了一个问题:留下来的人太多而使礼物数量可能不够,为此,加试了一道数学题:将一个正整数n分解成若干个互不相等的正整数的和,使得这些数的乘积最大,当主持人报出一个n后,请你立即将这个最大值报出来,现请你帮你的好友编一个程序来解决这个问题。
输入格式
输入中只有1个数n(其中1<=n<=1000)。
输出格式
输出中也是一个数,是乘积的最大值。
样例输入
7样例输出
12此题时将整数M划分成N个不同整数 使N个整数乘积最大 (Wikioi 2612 / RQNOJ 269 / TYVJ 1260)
首先我们不会分解出1
将M划分成1和(M-1) 乘积不会比M大
1.对于小于4的数 无法将它划分出乘积大于自身的数 所以就不划分
2.当M=4时 2+2=2*2 我们可以划分也可以不划分 为了方便 将它划分成2+2
3.当M>4时 保证不重复和不分解出1 分解出的数越多越好
M>4时 可以分解成2个整数乘积大于M
为了分解更多的数
1.可以将M分解成2+3+...+k一直到和大于等于M
若和=M 则此方案为最佳
否则必须删掉一个数
当比M大1时 删掉2 并将(k-1)变成k
当比M大w(w!=1)时 删掉w
2.分解成2+3+...+k<=M使得再加上k+1时大于M
则对于差w 将w分成w个1 从大到小加到分解的数上
若w>k-1 则加完一边后再继续从大到小加1
如分解6
2+3<6<2+3+4
2+3+4-6=3
将3分成3个1
加到3 2 上 还剩一个1
再加到4 3中的3上
由大到小的顺序 是为了保证不相同
代码如下
#include<iostream>#include<cstdio>#include<cstring>using namespace std;int s[11111];int ans[1111];int m,a,b,c,n;void print(int ans[1111]){ int a; for(a=1000;a>1;a--) if(ans[a])break; while(a) { cout<<ans[a]; a--; }}void jinwei(int ans[1111]){ int i; for(int i=1;i<=1000;i++) if(ans[i]>=10) { ans[i+1]=ans[i+1]+ans[i]/10; ans[i]%=10; }}void calc(){ int a,b; ans[1]=1; for(a=1;a<=n;a++) { for(b=1;b<=500;b++) ans[b]=ans[b]*s[a]; jinwei(ans); }}int main(){ cin>>m; for(a=1;m>s[a-1];a++) { s[a]=min(a+1,m); m-=s[a]; if(m<=s[a])break; } n=a; while(m) { for(a=n;a>=1;a--) { s[a]++; m--; if(m<=0)break; } } calc(); print(ans); return 0;}
对于可相同的整数划分(VIJOS 1033)
将整数M划分成N个整数 使N个整数乘积最大(Wikioi 3179)
将M划分成1和(M-1) 乘积不会比M大 故不分解出1
因此
1.对于小于4的数 无法将它划分出乘积大于自身的数 所以就不划分
2.当M=4时 2+2=2*2 我们可以划分也可以不划分 为了方便 将它划分成2+2
3.当M>4时 可证明M分解成若干整数的和 他们的积大于M
考虑分解成2个数的情况
当M为偶数时 (M/2)^2>M 解得M>4
当M为奇数时 ((M+1)/2)*((M-1)/2)>M 解得M>2*5^(1/2)
因此M>4时 可以分解成2个整数乘积大于M 需要将它分解
M>4时 令M=x+(M-x)
考虑y=x*(M-x) y表示数乘积比M大的值
y为二次函数 开口向下 在M/2时取到最大值 在(0,M/2)单调递增 在(M/2,M)单调递减
所以M为偶数时 分解成M/2+M/2
M为奇数时 分解成(M+1)/2+(M-1)/2
然后对分解后的数也尝试考虑1.2.3
这样做后 发现最后分解的数都为2和3
由于2*2*2<3*3而2+2+2=3+3
所以每分解成3个2 我们将它变成2个3
这样就可以求出最大的乘积
#include<iostream>#include<cstdio>using namespace std;int m,a,b,z[1011];void print(){ int a; for(a=1000;a>1;a--)if(z[a])break; while(a) { cout<<z[a];a--; } cout<<'\n';}void jinwei(){ for(int a=1;a<=1000;a++) if(z[a]>=10) { z[a+1]=z[a+1]+z[a]/10; z[a]%=10; }}void calc(){ z[1]=1; while(b) { z[1]*=2; b--; } while(a) { for(int k=1;k<=1000;k++)z[k]*=3; jinwei(); a--; } print();}int main(){ cin>>m; if(m<=4) { cout<<m<<'\n'; return 0; } while(m%3!=0) { b++; m-=2; } a=m/3; calc(); return 0;}
- 整数划分
- 整数划分
- 整数划分
- 整数划分
- 整数划分
- 整数划分
- 整数划分
- 整数划分
- 整数划分
- 整数划分
- 整数划分
- 整数划分
- 整数划分
- 整数划分
- 整数划分:
- 整数划分
- 整数划分
- 整数划分
- Alertable I/O
- 查找数组中第二大或者第二小的数值
- Android源码下载及开发环境的搭建
- String与数字及大小写转换
- ASP.NET上传图片
- 整数划分
- C/C++学习笔记(九)typedef的使用
- 使用Linux向磁盘写入镜像,制作启动盘等
- HTML5 drag & drop 拖拽与拖放简介
- websphere中部署ear包
- qt连接sqlite数据库(win下Qt5)
- Effective C++ 第二版 17)operator=检查自己 18)接口完整 19)成员和友元函数
- 在linux下怎么安装.bin文件
- 【一】JDK ,JRE ,JVM ,JavaEE SDK 介绍与比较