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的排座位
题目描述: 样例: 实现解释: 一道看似复杂但实际既是斐波那契变形的题目 知识点:递推,斐波那契 通过问题的描述,可以得到以下规律:(除了座位数为一时)男生坐最后时,倒数第二个一定是女生:女生坐最后, ...
随机推荐
- 虚拟化技术:Xen与KVM的对比
作为开源的虚拟化技术,对比Xen和KVM可以看到,Xen以6个无与伦比的优势领先:更好的可用资源.平台支持.可管理性.实施.动态迁移和性能基准. 可用资源:Xen的问世要比KVM早4年之久(两者分别是 ...
- CloudStack Ctrix官网版本
手动生成keystore keytool -genkey -keystore /etc/cloudstack/management/cloud.keystore -storepass "vm ...
- linux zip解压缩中文乱码
这里提供两个解决方案: 1.python处理下:https://gist.github.com/wangjiezhe/7841a350983a147b6d7e 2.java的zip4j:http:// ...
- [C++] Template Function _ Any number of parameters
Template Function _ Any number of parameters #include<iostream> #include<cstdarg> using ...
- [Jenkins] 执行SoapUI的task,里面包含多个Project,发出的报告也要求包含多个Project,设置邮件内容为HTML+CSS
执行SoapUI的task,里面包含多个Project,发出的报告也要求包含多个Project,设置邮件内容为HTML+CSS 如何保证样式在邮件内容中不丢失 <link title=" ...
- JSON Web Token(JWT)学习笔记
1.JWT 的Token 标准的Token由三个部分并以.(点号)连接方式组成,即 header.payload.signature,如下 eyJhbGciOiJIUzI1NiIsInR5cCI6Ik ...
- 实践作业3:白盒测试----总结与反思DAY12.
---恢复内容开始--- 阶段一:熟悉白盒测试方法 负责人:刘思佳 工作质量评价:用例设计详细,考虑到白盒测试基于代码,所以尽可能地覆盖更多的白盒测试方法,对系统可能存在的缺陷就更容易了解.对管理员和 ...
- [GO]结构体指针类型匿名字段
package main import "fmt" type Person struct { name string sex byte age int } type Student ...
- 在Mac OS下配置PHP开发环境
实在厌倦了windows无缘无故的宕机.病毒了吗,哈哈哈,这个跟我都没什么关系.准备使用下现如今牛X到不行的云平台没有办法只好研究下PHP. 现在的云平台支持的语言只有PHP.Java和Python. ...
- 编写高质量代码改善C#程序的157个建议——建议107:区分静态类和单例
建议107:区分静态类和单例 有一种观点认为:静态类可以作为单件模式的一种实现方式.事实上,这是不妥当的.按照传统的观点来看,单例是一个实例对象.而静态类并不满足这一点.静态类也直接违反面向对象三大特 ...