最大最小公倍数
来源:互联网 发布:mac做win8启动盘 编辑:程序博客网 时间:2024/05/21 01:46
【题目描述】
已知若干个正整数的和为S,求这若干个正整数的最小公倍数的最大值。
【输入】
第一行一个整数T,表示测试数据的组数。
接下来T行,每行包括一个正整数S,表示若干个正整数的和为S。
【输出】
输出T行,每行包括一个整数,表示和为S的若干个正整数的最小公倍数的最大值。
【样例输入】
2
4
7
【样例输出】
4
12
【数据范围限制】
40%的数据:S≤100;
80%的数据:S≤330,结果不会超过long long类型;
100%的数据:2≤S≤500,T≤10,结果不会超过25位整数。
【提示】
样例中第一组数据S=4,它能分解成S=1+1+1+1,S=1+1+2,S=1+3,S=2+2,S=4,很明显S=4时最小公倍数为4,是所有情况中最小公倍数最大的;第二组数据S=7,它能分解成S=3+4,3和4的最小公倍数是12,也是所有情况中最小公倍数最大的。
【题解】
这道题真是 害人不浅 啊!题目描述那么难懂就算了,还来个高精度!
我比赛时看到题目,哇塞!好难啊!我一直想着怎样把S拆成几个数,并没有找规律(因为最近经常做暴力水法就能过的题)。最后决定使用递归枚举 拆分S的所有情况,再找出最小值更新答案。
结果果然不出我所料,时间超限30!
30分的做法我就不细讲了,毕竟那个并不是正解。
这道题目其实是一道DP!我们可以把S拆分成这个样子:
其中,x1,x2,x3……,xi均为质数。
那么答案就等于
为什么要拆成质数呢?我们可以设
下面我们来设状态吧!
我们可以设f[i]为 和为i的若干个质数的积的最大值 那么我们就可以写出状态转移方程了:
其中,j 枚举的是质数,k 枚举的是系数。
额……怎么这题竟然是一道DP?!
温馨提示:
- 我们可以先算出2~500的所有质数,然后DP,最后读入s(只要立刻输出f[s]就可以了)
- DP过程是三重循环的,最外层是j,枚举质数;然后是i,枚举1~500的所有数;最后是k,枚举系数。
- 记得打高精度!其实我们并不需要打出高精度 加、减、乘、除的所有运算,只要打 高精度乘低精度的运算 和 高精度数的判断操作 即可!
DP前记得把f数组直接初始化为1(不然答案都会是0哟)
下面就是正确代码,希望大家不要直接拷到oj上提交。
#include<cstdio>#include<cstring>#include<cmath>using namespace std;struct node{ int len,a[120]; node() { memset(a,0,sizeof(a)); len=1; }}f[510];int s[500];node chengfa_x(node n1,int x)//这里是高精度乘低精度!{ node no;int i; no.len=n1.len; for(i=1;i<=no.len;i++) no.a[i]=n1.a[i]*x; for(i=1;i<=no.len;i++) { no.a[i+1]+=no.a[i]/10; no.a[i]%=10; } i=no.len; while(no.a[i+1]>0) { i++; no.a[i+1]=no.a[i]/10; no.a[i]%=10; } while((no.a[i]==0)&&(i>1)) i--; no.len=i; return no;}bool pd(int k)//判断素数{ int tt=sqrt(k),i; for(i=2;i<=tt;i++) { if(k%i==0) return false; } return true;}node max(node x,node y)//高精度取max值{ if(x.len>y.len) return x; if(x.len<y.len) return y; for(int i=x.len;i>=1;i--) { if(x.a[i]>y.a[i]) return x; else if(x.a[i]<y.a[i]) return y; } return y;}int main(){ int t,i,j,c,sum=0,k,p; node T; scanf("%d",&t); for(i=2;i<=500;i++) if(pd(i)) { s[++sum]=i; } for(i=0;i<=500;i++) f[i].a[1]=1;//初始化 for(j=sum;j>0;j--)//DP过程 { for(i=500;i>=1;i--) { p=1; for(k=1;k<=8;k++) { p=p*s[j]; if(p>i) break; else { f[i]=max(f[i],chengfa_x(f[i-p],p)); } } } } while(t--) { scanf("%d",&c); for(i=f[c].len;i>=1;i--) printf("%d",f[c].a[i]); printf("\n");//输入一个,输出一个 } return 0;}
- 最大最小公倍数
- 最大最小公倍数
- 最大最小公倍数
- 最大最小公倍数
- 最大最小公倍数
- 最大最小公倍数
- 最大最小公倍数
- 最大最小公倍数
- 最大最小公倍数
- 最大最小公倍数
- 最大最小公倍数
- 最大最小公倍数
- 最大最小公倍数
- 最大最小公倍数
- 最大最小公倍数
- 最大最小公倍数
- 最大最小公倍数
- 最大最小公倍数
- 四、JSP的一个登入例子
- 三十分钟掌握STL
- android.support.v4.app.Fragment和android.app.Fragment区别
- 【mysql】配置MySQL,解决安装过程中的问题
- SVN的安装与常用功能使用以及解决安装配置过程中的一些错误
- 最大最小公倍数
- Linux Shell脚本基础(二)
- 设计模式
- Java字符串过滤回车和换行符
- 排列组合
- CIFS文件系统
- 启发式算法给Gurobi 输入初始解
- java 常用集合list与Set、Map区别及适用场景总结
- widerface转换为pascal数据集的格式