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的更多相关文章

  1. 2016级算法第二次上机-G.ModricWang's Real QuickSort

    873 思路 这是一道非常基础的题,目的是帮助大家回顾快排相关的知识.大家完成此题之后应该就对快排有比较深刻的印象了. 对于整个快排的流程,题目描述中已经给了清晰完整的伪代码.需要自己加工的部分就是, ...

  2. 2016级算法第二次上机-E.AlvinZH的儿时梦想——运动员篇

    862-AlvinZH的儿时梦想--运动员篇 思路 难题. 应该想到,不管给出的数据如何,每一个淘汰的人不会对最终答案产生任何影响,所以每次淘汰就把人除掉就可以了,最后剩下的两个人计算它们从开始到相遇 ...

  3. 2016级算法第二次上机-D.Bamboo的饼干

    Bamboo的饼干 分析 从两个数组中各取一个数,使两者相加等于给定值.要注意去重和排序 难度不大,方法很多,基本只要不大于O(n^2 ) 的都可以过.本意想考察二分搜索 还可以借助stl中的map, ...

  4. 2016级算法第二次上机-C.AlvinZH的儿时梦想——坦克篇

    872 AlvinZH的儿时梦想----坦克篇 思路 简单题.仔细看题,题目意在找到直线穿过的矩形数最小,不能从两边穿过.那么我们只要知道每一行矩形之间的空隙位置就可以了. 如果这里用二维数组记住每一 ...

  5. 2016级算法第二次上机-B.Bamboo的OS实验

    Bamboo的OS实验 分析 首先理解题意,要完成不同数量的不同命令,但是完成相同的命令之间必须有n个间隔,为使得时间最短,自然优先用其他命令来填充这n分钟的时间,由于数量少的命令可以用来填充空隙,所 ...

  6. 2016级算法第二次上机-A.画个圈圈诅咒你

    890 画个圈圈诅咒你 思路 简单题.题目中的圆并没有什么实际作用,简化成线段重合问题会更好理解些. 暴力解法:使用双重for循环会T到想哭,记住最直接的方法一般是过不了题的. 解法一:二分查找.空间 ...

  7. 2016级算法期末模拟练习赛-F.AlvinZH的青春记忆IV

    1086 AlvinZH的青春记忆IV 思路 难题,动态规划. 这是一道很有意思的题,因为它不仅卡了时间,也卡了空间,而且卡的很妙很迷. 光是理解题意已经有点难度,简化题意:两串数字序列,相等的数字定 ...

  8. 题解:2018级算法第二次上机 Zexal的流水线问题

    题目描述: 样例: 实现解释: 最基础的流水线调度问题,甚至没有开始和结束的值 实现方法即得出状态转移方程后完善即可,设a[][i]存储着第一二条线上各家的时间花费,t[][i]存储着i处进行线路切换 ...

  9. 题解:2018级算法第二次上机 Zexal的排座位

    题目描述: 样例: 实现解释: 一道看似复杂但实际既是斐波那契变形的题目 知识点:递推,斐波那契 通过问题的描述,可以得到以下规律:(除了座位数为一时)男生坐最后时,倒数第二个一定是女生:女生坐最后, ...

随机推荐

  1. Xen的源码安装及dom0,domU的设置

    Xen作为一种应用广泛的虚拟机方案,无论是在工业还是教育领域都发挥着巨大的作用.Xen不仅有其引以为豪的Paravirtualization实现,还有基于硬件支持的HVM实现.对于Xen,Ubuntu ...

  2. 76-Relatives-欧拉函数

    http://poj.org/problem?id=2407 Relatives Time Limit: 1000MS   Memory Limit: 65536K Total Submissions ...

  3. QuickSort模板

    #include <iostream> using namespace std; struct node { int index; char name[20]; }; node data[ ...

  4. CF 438E The Child and Binary Tree

    BZOJ 3625 吐槽 BZOJ上至今没有卡过去,太慢了卡得我不敢交了…… 一件很奇怪的事情就是不管是本地还是自己上传数据到OJ测试都远远没有到达时限. 本题做法 设$f_i$表示权值为$i$的二叉 ...

  5. hdu Lovekey(水题)

    #include<stdio.h> #include<string.h> ]; int main() { ],s2[]; int l1,l2,i,j,k; while(scan ...

  6. C#调用COM组件遇到的问题及解决办法

    1.无法嵌入互操作类型"xxx",请改用适用的接口. 解决办法: - 将所引用的程序集的[嵌入互操作类型]属性设置为[False]. 2.System.Runtime.Intero ...

  7. mysql 用户创建,修改和忘记root密码的操作

    #创建用户CREATE USER 'zzq'@'localhost' IDENTIFIED by 'zzq';#flush privileges 命令本质上的作用是将当前user和privilige表 ...

  8. jquery 常用工具方法

    inArray(value, array [, fromIndex ])方法类似于原生javascript的indexOf()方法,没有找到匹配元素时它返回-1.如果数组第一个元素匹配参数,那么$.i ...

  9. [你必须知道的异步编程]——异步编程模型(APM)

    本专题概要: 引言 你知道APM吗? 你想知道如何使用异步编程模型编写代码吗? 使用委托也可以实现异步编程,你知道否? 小结 一.引言 在前面的C#基础知识系列中 介绍了从C#1.0——C#4.0中一 ...

  10. mysql建外键失败

    1. 修改引擎:(设计表-->选项-->引擎:InnoDB) 2. 检查外键类型是否一致: