hihoCoder #1072 辅导
题意
$\DeclareMathOperator{\lcm}{lcm}$选 $k$ ($k\le 10$) 个 $1$ 到 $n$($n\le 10^9$)之间的整数(可以相同),使得 $\lcm(a_1, \dots, a_k)$ 最大。
题解
这是 hihoCoder 挑战赛 #6 的 B 题,CLJ(WJMZBMR) 出的。CLJ 的题解:
首先我们注意到,如果你选择了两个不互质的 $a, b$,那么不妨把 $a$ 换成 $a/(a,b)$。显然 LCM 还是不变的。
这意味着存在一组最优解使得所有选择的数都两两互质。
那么我们不妨使用暴搜,首先我们注意到我们至少可以选择比 $n$ 小的最大的 $k$ 个质数来当做初始解。
然后我们从大到小枚举是否使用,搜到 $x$ 时,假如当前最优解是 $ans$, 当前 LCM 是 $w$, 如果还能选择 $t$ 个, 假如 $wx^t \le ans$,那么显然已经无法得出更优的解了,就可以剪枝了。
首先需要指出,上面题解中
如果你选择了两个不互质的数 $a, b$,那么不妨把 $a$ 换成 $a/(a,b)$ 。显然 LCM 还是不变的。
这个结论是错误的,很容易举出反例:$a=4, b=2$,可能是作者笔误。不过,对于不互质的两个数 $a,b$ ,确实存在两个互质的数 $a',b'$ ($a'\le a, b'\le b$),使得 $\lcm(a',b') = \lcm(a,b)$。
写出 $a, b$ 两数的质因子展开式,设
$$
\begin{align}
a = p_1^{i_1} p_2^{i_2}\dots p_n^{i_n} \notag\
b = p_1^{j_1} p_2^{j_2}\dots p_n^{j_n} \notag
\end{align}
$$
在 $a$,$b$ 展开式中,只保留幂次较大的项便得到了 $a'$, $b'$。
至此,我遇到了一个困难:如何求比 $n$($n\le 10^9$)小的最大的 $k$($k\le 10$)个素数?
当然,求出 $k$ 个最大的素数并非我们的最终目的,这样做只是为了得到一个较大的初始解,求出不满 $k$ 个最大的素数也无妨,从而我们可以暴力判断后若干(比如 100)个数。另外,应当能看出初始解是否取一个较大的值,对程序运行时间影响并不大,将其取为 $n$ 甚至 $0$ 也可以。
复杂度
??从递归深度开始考虑??(大误,递归深度最大即为 $k$ 啊!!!我真是沙茶)
Implementation
#include <bits/stdc++.h>
using namespace std;
vector<int> a;
long long res;
long double product;
const int mod = 1e9 + 7;
int n, k;
void dfs(int x, long double cur_prod){
    if(a.size() == k || x == 1){
        // product = cur_rod;
        res = 1;
        product = cur_prod;
        for(auto i: a){
            // product *= i;
            res *= i, res %= mod;
        }
        return;
    }
    if(cur_prod * pow((long double)x, k - a.size()) <= product)
        return; // 剪枝
    bool flag = true;
    for(auto i: a)
        if(__gcd(x, i) != 1){
            flag = false;
            break;
        }
    if(flag){
        a.push_back(x);
        dfs(x-1, cur_prod * x);
        a.pop_back();
    }
    dfs(x-1, cur_prod);
}
int main(){
    // int n, k;
    cin >> n >> k;
    // product = n == 1 ? n : n * (n - 1);
    product = n;
    res = n;
    dfs(n, 1);
    cout << res << endl;
    return 0;
}
上面代码中的 dfs() 还有一种写法:
void dfs(int x, long double cur_prod){
    if(a.size() == k || x == 1){
        res = 1;
        product = cur_prod;
        for(auto i: a){
            res *= i, res %= mod;
        }
        return;
    }
    for(int i = x; ; i--){
        bool flag = true;
        for(auto j: a){
            if(__gcd(i, j) != 1){
                flag = false;
                break;
            }
        }
        if(!flag) continue;
        if(cur_prod * pow((long double)i, k - a.size()) <= product)
            break;
        a.push_back(i);
        dfs(i, cur_prod * i);
        a.pop_back();
    }
}
hihoCoder #1072 辅导的更多相关文章
- hihocoder -1121-二分图的判定
		hihocoder -1121-二分图的判定 1121 : 二分图一•二分图判定 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 大家好,我是小Hi和小Ho的小伙伴Net ... 
- Hihocoder 太阁最新面经算法竞赛18
		Hihocoder 太阁最新面经算法竞赛18 source: https://hihocoder.com/contest/hihointerview27/problems 题目1 : Big Plus ... 
- hihoCoder太阁最新面经算法竞赛15
		hihoCoder太阁最新面经算法竞赛15 Link: http://hihocoder.com/contest/hihointerview24 题目1 : Boarding Passes 时间限制: ... 
- 【hihoCoder 1454】【hiho挑战赛25】【坑】Rikka with Tree II
		http://hihocoder.com/problemset/problem/1454 调了好长时间,谜之WA... 等我以后学好dp再来看为什么吧,先弃坑(╯‵□′)╯︵┻━┻ #include& ... 
- 【hihocoder#1413】Rikka with String     后缀自动机 + 差分
		搞了一上午+接近一下午这个题,然后被屠了个稀烂,默默仰慕一晚上学会SAM的以及半天4道SAM的hxy大爷. 题目链接:http://hihocoder.com/problemset/problem/1 ... 
- 【hihoCoder】1148:2月29日
		问题:http://hihocoder.com/problemset/problem/1148 给定两个日期,计算这两个日期之间有多少个2月29日(包括起始日期). 思路: 1. 将问题转换成求两个日 ... 
- 【hihoCoder】1288 : Font Size
		题目:http://hihocoder.com/problemset/problem/1288 手机屏幕大小为 W(宽) * H(长),一篇文章有N段,每段有ai个字,要求使得该文章占用的页数不超过P ... 
- 【hihoCoder】1082: 然而沼跃鱼早就看穿了一切
		题目:http://hihocoder.com/problemset/problem/1082 输入一个字符串,将其中特定的单词替换成另一个单词 代码注意点: 1. getline(istre ... 
- 【hihoCoder】1121:二分图一·二分图判定
		题目 http://hihocoder.com/problemset/problem/1121 无向图上有N个点,两两之间可以有连线,共有M条连线. 如果对所有点进行涂色(白/黑),判定是否存 ... 
随机推荐
- Cause: java.lang.UnsupportedOperationException
			运行web项目的时候出现以下错误: ### Cause: java.lang.UnsupportedOperationException at org.mybatis.spring.MyBati ... 
- UVA 11627  Slalom(二分)
			二分,判断的时候,一个点一个点的考虑肯定是不行啦,考虑的单位是一个区间, 每次左端点尽量向左边移动,右端点尽量向右,得到下次可以达到的范围,检查一下和下一个区间有没有交集. #include<b ... 
- [学习笔记]Linux下mysql的基础操作
			命令 #查看版本 mysql --version #进入mysql 命令 mysql -u root -p mysql -u root@localhost (没有密码的情况) #创建数据库 c ... 
- C++ Stack 与String
			// ConsoleApplication1.cpp : 此文件包含 "main" 函数.程序执行将在此处开始并结束. // #include "pch.h" ... 
- spring5之SAXParseException:cvc-elt.1: 找不到元素 “beans” 的声明
			之前SSM项目一直报错,就是找不到错误 气啊 后来在网上找到了答案:燕来spring5之后就不再需要写版本号了 
- java基础—代理(proxy)
			一.代理的概念 动态代理技术是整个java技术中最重要的一个技术,它是学习java框架的基础,不会动态代理技术,那么在学习Spring这些框架时是学不明白的. 动态代理技术就是用来产生一个对象的代理对 ... 
- 洛谷 4219/BZOJ 4530 大融合
			4530: [Bjoi2014]大融合 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 990 Solved: 604[Submit][Status] ... 
- mysql 在线添加字段
			使用工具pt-online-schema-change #! /bin/bash stime=`date +%s` echo "增加字段开始测试时间为:`date +%H:%M:%S`&qu ... 
- C# WPF 粘贴板记录器
			工作学习中需要搜索很多资料,有建立文档对遇到过的问题进行记录,但是一来麻烦,二来有些当时认为不重要的事情,也许一段时间后认为是重要的,需要记录的,却又一时找不到,浪费时间做重复的事情.正好借着这个机会 ... 
- MYSQL导入数据:Table XXX doesn't exist的解决
			数据表为Innodb引擎 data文件夹中存在数据表的frm文件,但在phpmyadmin中看不到这些表,于是采用导入sql文件的方式进行恢复 1.直接导入原数据表的sql文件,原frm文件不删除 出 ... 
