2016级算法第二次上机-F.ModricWang's Number Theory II
891 ModricWang's Number Theory II
思路
使得序列的最大公约数不为1,就是大于等于2,就是找到一个大于等于2的数,它能够整除序列中的所有数。
考虑使得一个数d整除数组中所有数的代价:
如果一个数不能被b整除,那么可以花费x的代价删掉它,或者通过多次加1使得它可以被d整除,代价应该为 \((d - a[i]\%d) * y\) , \((a[i] \% d == 0s时特判,应该为0)\)
令 \(l = x / y\)
如果\(d - a[i] \% d <= l\) \((a[i]\%d != 0)\), 这个数产生的代价是 \((d - a[i] \% d) * y\) , 否则是\(x\)。
所有代价求和就是总代价,最小的总代价就是答案。
但是这样枚举了d和a[i], 复杂度是\(O(n^2)\) 的。
考虑将a[i]换一种方式存储:b[i]表示值为i的数出现的次数。
这样d可以将b分成如下若干段:
\([0, d - 1], [d, d * 2 - 1], [d * 2, d * 3 - 1], ... ,[d * i, d * (i + 1) - 1]\)
对于每一段而言,
\([d * (i + 1) - l, d * (i + 1) - 1]\) 内的数应该通过多次加1变成\(d * (i + 1)\) ,
代价应为 \((该区间内数的个数 * d * (i + 1) - 该区间内的数之和) * y\)
\([d * i + 1 , d * (i + 1) - l - 1]\) 内的数应该直接删除,
代价应为 \(该区间内的个数 * x\)
通过构造相应的前缀和数组,上述操作均可以在\(O(1)\) 的时间复杂度内完成
具体操作时应该注意边界
因为合数会被质数整除,因此d可以只枚举质数。
计算时间复杂度需要一些数论知识。首先素数密度(也就是 \(\frac{小于n的素数}{n}\) )可以参见oeis A006880,一个近似解析式为 \(\frac{1}{ln(n)}\),那么\(小于n的素数的总个数\)可以近似为 \(\frac{n}{ln(n)}\)
设小于等于n的素数为\(prime[i]\),素数总数为\(P\),取近似\(P=\frac{n}{ln(n)}\)
求结果部分的复杂度可以写为 \(\sum_{1}^{P} \frac{n}{prime[i]}\)
参见wikipedia,素数的倒数和又可以近似为 \(\sum_{1}^{p} \frac{1}{prime[i]}=ln(ln(n))\)
因此 \(\sum_{1}^{P} \frac{n}{prime[i]} = O(n* ln(ln(n)))\)
这里得到了计算结果部分的复杂度,还需要加上求素数这个过程的时间复杂度。如果使用朴素筛法,求复杂度的过程正好的上文所述的完全一致,其复杂度为\(O(n*ln(ln(n)))\)。如果使用欧拉筛求素数,复杂度为\(O(n)\)。
因此\(O(运行时间)=O(求素数)+O(计算结果)=O(n*ln(ln(n)))\)
代码
#include<iostream>
#include<cstring>
using namespace std;
const long long Max_Ai = 1000000*2;
long long n, x, y, l;
long long nums[Max_Ai + 10];
long long s[Max_Ai + 10], sum[Max_Ai + 10];
bool valid[Max_Ai + 10];
long long prime[Max_Ai + 10];
long long tot;
//线性筛求素数
void init_prime() {
memset(valid, true, sizeof(valid));
for (int i = 2; i <= Max_Ai; i++) {
if (valid[i]) prime[++tot] = i;
for (int j = 1; j <= tot && i*prime[j] <= Max_Ai; j++) {
valid[i*prime[j]] = false;
if (i%prime[j]==0) break;
}
}
}
int main() {
#ifdef ONLINE_JUDGE
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
#endif
init_prime();
cin >> n >> x >> y;
l = x/y;
for (long long i = 1; i <= n; i++) {
long long p;
cin >> p;
nums[p]++; //这是一种比较特别的数字记录方法,原理类似于基数排序radix sort
}
for (long long i = 1; i <= Max_Ai; i++) {
s[i] = s[i - 1] + nums[i]; //数量和
sum[i] = sum[i - 1] + nums[i]*i; //前缀和
}
auto min_cost = (long long) 1e18;
for (long long i = 1; i <= tot; i++) {
long long k = prime[i];
long long now_cost = 0;
for (long long j = 0; j <= Max_Ai; j += k) {
long long mid = max(j + k - l - 1, j);
long long bound = min(j + k - 1, Max_Ai);
if (bound > mid) {
now_cost += ((s[bound] - s[mid])*(j + k) - (sum[bound] - sum[mid]))*y;
now_cost += (s[mid] - s[j])*x;
} else {
now_cost += (s[bound] - s[j])*x;
}
}
min_cost = min(min_cost, now_cost);
}
cout << min_cost << "\n";
return 0;
}
2016级算法第二次上机-F.ModricWang's Number Theory II的更多相关文章
- 2016级算法第二次上机-G.ModricWang's Real QuickSort
873 思路 这是一道非常基础的题,目的是帮助大家回顾快排相关的知识.大家完成此题之后应该就对快排有比较深刻的印象了. 对于整个快排的流程,题目描述中已经给了清晰完整的伪代码.需要自己加工的部分就是, ...
- 2016级算法第二次上机-E.AlvinZH的儿时梦想——运动员篇
862-AlvinZH的儿时梦想--运动员篇 思路 难题. 应该想到,不管给出的数据如何,每一个淘汰的人不会对最终答案产生任何影响,所以每次淘汰就把人除掉就可以了,最后剩下的两个人计算它们从开始到相遇 ...
- 2016级算法第二次上机-D.Bamboo的饼干
Bamboo的饼干 分析 从两个数组中各取一个数,使两者相加等于给定值.要注意去重和排序 难度不大,方法很多,基本只要不大于O(n^2 ) 的都可以过.本意想考察二分搜索 还可以借助stl中的map, ...
- 2016级算法第二次上机-C.AlvinZH的儿时梦想——坦克篇
872 AlvinZH的儿时梦想----坦克篇 思路 简单题.仔细看题,题目意在找到直线穿过的矩形数最小,不能从两边穿过.那么我们只要知道每一行矩形之间的空隙位置就可以了. 如果这里用二维数组记住每一 ...
- 2016级算法第二次上机-B.Bamboo的OS实验
Bamboo的OS实验 分析 首先理解题意,要完成不同数量的不同命令,但是完成相同的命令之间必须有n个间隔,为使得时间最短,自然优先用其他命令来填充这n分钟的时间,由于数量少的命令可以用来填充空隙,所 ...
- 2016级算法第二次上机-A.画个圈圈诅咒你
890 画个圈圈诅咒你 思路 简单题.题目中的圆并没有什么实际作用,简化成线段重合问题会更好理解些. 暴力解法:使用双重for循环会T到想哭,记住最直接的方法一般是过不了题的. 解法一:二分查找.空间 ...
- 2016级算法期末模拟练习赛-F.AlvinZH的青春记忆IV
1086 AlvinZH的青春记忆IV 思路 难题,动态规划. 这是一道很有意思的题,因为它不仅卡了时间,也卡了空间,而且卡的很妙很迷. 光是理解题意已经有点难度,简化题意:两串数字序列,相等的数字定 ...
- 题解:2018级算法第二次上机 Zexal的流水线问题
题目描述: 样例: 实现解释: 最基础的流水线调度问题,甚至没有开始和结束的值 实现方法即得出状态转移方程后完善即可,设a[][i]存储着第一二条线上各家的时间花费,t[][i]存储着i处进行线路切换 ...
- 题解:2018级算法第二次上机 Zexal的排座位
题目描述: 样例: 实现解释: 一道看似复杂但实际既是斐波那契变形的题目 知识点:递推,斐波那契 通过问题的描述,可以得到以下规律:(除了座位数为一时)男生坐最后时,倒数第二个一定是女生:女生坐最后, ...
随机推荐
- HBase数据读写流程(1.3.1)
===数据写入流程=== 源码:https://github.com/apache/hbase/blob/master/hbase-server/src/main/java/org/apache/ha ...
- STL扩展容器
string | array | hash 1. string - 可以视为以字符为元素的一种容器, 可以在字符上进行遍历, 提供begin()/end() - 为了支持迭代器和迭代器适配器 , st ...
- Windows下如何安装MongoDB
下载地址: http://www.mongodb.org/downloads 我下载的是:mongodb-win32-x86_64-2008plus-2.6.6 解压到:D:\soft 同时在该目录下 ...
- [GO]定时器的停止和重置
package main import ( "time" "fmt" ) func main() { timer := time.NewTimer( * tim ...
- javascript总结20: 前端必读,浏览器内部工作原理(转)
目录 一.介绍 二.渲染引擎 三.解析与DOM树构建 四.渲染树构建 五.布局 六.绘制 七.动态变化 八.渲染引擎的线程 九.CSS2可视模型 英文原文:How Browsers Work: Beh ...
- Lua的文件IO操作
Lua 标准库 - 输入输出处理(input and output facilities) 转载于:http://blog.csdn.net/duanxuyun 文本Tag: Lua [IT168 技 ...
- 编写高质量代码改善C#程序的157个建议——建议148:不重复代码
建议148:不重复代码 如果发现重复的代码,则意味着我们需要整顿一下,在继续前进. 重复的代码让我们的软件行为不一致.举例来说,如果存在两处相同的加密代码.结果在某一天,我们发现加密代码有个小Bug, ...
- 编写高质量代码改善C#程序的157个建议——建议98:用params减少重复参数
建议98:用params减少重复参数 如果方法的参数数目不定,且参数类型一致,则可以使用params关键字减少重复参数声明. void Method1(string str, object a){} ...
- Sweetkang 的机器学习实验室 (1)
前言 近年来,Machine Learning 在许多领域上已然取得了可喜的成就,非常火热.就我个人来讲,有意将业余 Sport Programming 的范围扩展一下,譬如 Topcoder Mar ...
- 安装了IntelliJ IDEA中文输入法光标不跟随处理办法
安装了IntelliJ IDEA 2017.2.3版本发现搜狗输入法中文输入的时候光标不跟随,而且存在卡屏的现象,网上找了很多办法试了之后都不管用.最后在这里找到了解决方案,亲测可用! 首先,将IDE ...