题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=3092

Least common multiple

Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
#### 问题描述
> Partychen like to do mathematical problems. One day, when he was doing on a least common multiple(LCM) problem, he suddenly thought of a very interesting question: if given a number of S, and we divided S into some numbers , then what is the largest LCM of these numbers? partychen thought this problems for a long time but with no result, so he turned to you for help!
> Since the answer can very big,you should give the answer modulo M.
#### 输入
> There are many groups of test case.On each test case only two integers S( 0 Output the largest LCM modulo M of given S.
####样例输入
> 6 23

样例输出

6

题意

给你一个n,求把n拆成若干个数的和,要求这些数的最小公倍数最大。最后输出%M.

题解

由于最大公倍数会爆,无法直接维护,所以我们可以通过取对数的方式,得到大小,确定转移方向,然后利用这个去维护最优解。

这道题需要用到两个贪心策略:

1、只选质数(或质数的幂)(22*3=12,还不如22+3=7。)

2、每个质数只选一个(如果你拆出39=3+9+27,明显,只有27是有用的。。)

然后就可以转换成01背包求解了(贪心策略2决定了这是01背包!不是完全背包)

代码

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<ctime>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#include<sstream>
using namespace std;
#define X first
#define Y second
#define mkp make_pair
#define lson (o<<1)
#define rson ((o<<1)|1)
#define mid (l+(r-l)/2)
#define sz() size()
#define pb(v) push_back(v)
#define all(o) (o).begin(),(o).end()
#define clr(a,v) memset(a,v,sizeof(a))
#define bug(a) cout<<#a<<" = "<<a<<endl
#define rep(i,a,b) for(int i=a;i<(b);i++)
#define scf scanf
#define prf printf typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<pair<int,int> > VPII; const int INF=0x3f3f3f3f;
const LL INFL=0x3f3f3f3f3f3f3f3fLL;
const double eps=1e-8;
const double PI = acos(-1.0); //start---------------------------------------------------------------------- const int maxn=3333; double dp[maxn];
LL ans[maxn]; bool pri[maxn];
VI arr;
void pre() {
clr(pri,0);
for(int i=2; i*i<maxn; i++) {
if(!pri[i]) {
for(int j=i*i; j<maxn; j+=i) {
pri[j]=true;
}
}
}
for(int i=2; i<maxn; i++) if(!pri[i]) arr.pb(i);
} int main() {
pre();
int S,M;
while(scf("%d%d",&S,&M)==2) {
clr(dp,0);
double Ma=-1;
LL last=1;
for(int i=0; i<=S; i++) ans[i]=1;
//01背包
for(int i=0; arr[i]<=S; i++) {
for(int j=S; j>=arr[i]; j--) {
for(int k=arr[i]; k<=j; k*=arr[i]) {
if(dp[j]<dp[j-k]+log10(k)) {
dp[j]=dp[j-k]+log10(k);
ans[j]=ans[j-k]*k%M;
}
}
if(Ma<dp[j]+eps) {
Ma=dp[j];
last=ans[j];
}
}
}
prf("%I64d\n",last);
} return 0;
} //end-----------------------------------------------------------------------

HDU 3092 Least common multiple 01背包的更多相关文章

  1. 背包系列练习及总结(hud 2602 && hdu 2844 Coins && hdu 2159 && poj 1170 Shopping Offers && hdu 3092 Least common multiple && poj 1015 Jury Compromise)

    作为一个oier,以及大学acm党背包是必不可少的一部分.好久没做背包类动规了.久违地练习下-.- dd__engi的背包九讲:http://love-oriented.com/pack/ 鸣谢htt ...

  2. ACM学习历程—HDU 3092 Least common multiple(数论 && 动态规划 && 大数)

    Description Partychen like to do mathematical problems. One day, when he was doing on a least common ...

  3. hdu 3092 Least common multiple

    思路: 容易知道,分解成素数的lcm肯定是最大的,因为假设分解成2个合数,设定x为他们的 最大公约数, 那么他们的最小公倍数就要减少x倍了 然后如果是素数之间的最小公倍数,那么就只是他们的乘积,同样的 ...

  4. HDU 5234 Happy birthday --- 三维01背包

    HDU 5234 题目大意:给定n,m,k,以及n*m(n行m列)个数,k为背包容量,从(1,1)开始只能往下走或往右走,求到达(m,n)时能获得的最大价值 解题思路:dp[i][j][k]表示在位置 ...

  5. HDOJ(HDU).3466 Dividing coins ( DP 01背包 无后效性的理解)

    HDOJ(HDU).3466 Dividing coins ( DP 01背包 无后效性的理解) 题意分析 要先排序,在做01背包,否则不满足无后效性,为什么呢? 等我理解了再补上. 代码总览 #in ...

  6. HDOJ(HDU).2546 饭卡(DP 01背包)

    HDOJ(HDU).2546 饭卡(DP 01背包) 题意分析 首先要对钱数小于5的时候特别处理,直接输出0.若钱数大于5,所有菜按价格排序,背包容量为钱数-5,对除去价格最贵的所有菜做01背包.因为 ...

  7. HDOJ(HDU).2602 Bone Collector (DP 01背包)

    HDOJ(HDU).2602 Bone Collector (DP 01背包) 题意分析 01背包的裸题 #include <iostream> #include <cstdio&g ...

  8. HDU 1864 最大报销额 0-1背包

    HDU 1864 最大报销额 0-1背包 题意 现有一笔经费可以报销一定额度的发票.允许报销的发票类型包括买图书(A类).文具(B类).差旅(C类),要求每张发票的总额不得超过1000元,每张发票上, ...

  9. hdu 2639 第k大01背包

    求每个状态里的k优解,然后合并 /* HDU 2639 求01背包的第k大解. 合并两个有序序列 */ #include<stdio.h> #include<iostream> ...

随机推荐

  1. 关于Linux的交叉编译环境配置中的问题

    Linux的交叉编译arm-linux-gcc搭建时,安装结束却无法查看版本.输入以下命令查看Ubuntu的版本: uname -a 可以看到此Ubuntu为64位16.04.1版本,所以需要下载32 ...

  2. python3爬虫-通过selenium获取到dj商品

    from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.c ...

  3. hadoop--hive数据仓库

    一.hive概述 Hive是基于 Hadoop 的一个[数据仓库工具],可以将结构化的数据文件映射为一张数据库表,并提供简单的 sql 查询功能,可以将 sql 语句转换为 MapReduce 任务进 ...

  4. 20155327 2017-2018-2 《Java程序设计》第一周学习总结

    20155327 2017-2018-2 <Java程序设计>第一周学习总结 教材学习内容总结 三大平台: 1.Java SE:JVM,JRE,JDK,java语言 JVM:Java虚拟机 ...

  5. 【HNOI2013】消毒

    题面 题解 当只有二维时,就是一个二分图匹配的板子题 三维的时候就很好做了,暴力枚举一维的情况,因为\(\min(x,y,z) = \sqrt{5000} < 18\),于是时间复杂度有保证 代 ...

  6. c#总结:datatable的方法大全

    最近在做一个数据处理,保存到datatable中,在过程中了解了datatable一些用法,总结一下: //定义 DataTable dt = new DataTable(); //写入列名: htT ...

  7. [BZOJ4883][Lydsy1705月赛]棋盘上的守卫[最小基环树森林]

    题意 有一大小为 \(n*m\) 的棋盘,要在一些位置放置一些守卫,每个守卫只能保护当前行列之一,同时在每个格子放置守卫有一个代价 \(w\) ,问要使得所有格子都能够被保护,需要最少多少的代价. \ ...

  8. 巧用 Python 找工作(资料在文末)

    前言 近年来 Python 之火大家都有感而知,那亲们知道北京的 Python 开发岗位.运维开发岗位招聘地域都是如何分布的吗?薪水如何?是否有前景等等,这些数据呢直接通过招聘信息来了解到企业用人是最 ...

  9. 使用efwplusScript开发Winform程序【像小程序那样开发PC软件】

    一.前言 本人从事多年医疗管理软件的开发,在医院大多数的软件都还是CS程序,BS程序很少,对于使用者来说CS的操作体验确实比BS的要好. 1.CS的缺点就是升级麻烦,每次有新版本都需要所有客户端操作升 ...

  10. hdu2795 Billboard(线段树单点修改)

    传送门 结点中的l和r表示层数,maxx表示这层最多还剩下多少宽度.根据公告的宽度取找到可以放的那一层 找到后返回层数,并修改maxx #include<bits/stdc++.h> us ...