codeforces 580B Arpa and a list of numbers 前缀和+思维+分块 (调和级数)
来源:互联网 发布:开票软件商品编码 编辑:程序博客网 时间:2024/05/18 23:54
题目链接
题意:
给出N个数,删除一个数的花费是X,改变一个数从num变成num+1的花费是Y,问将整个序列的Gcd改成不是1的最小花费。
思路:
首先考虑枚举gcd,我们知道gcd为素数肯定最优了,因为你枚举质数的倍数为gcd的话,排着枚举肯定会先枚举到质数,不是最优.
1e6以内的素数大约8e4个,而元素最多有5e5.这样还是会TLE。
我们知道,基于贪心的思想肯定是我们枚举一个gcd,然后对于一些数是删掉他最优一些是直接每次+1最优.
1.如果x<y 那么不需要每次+1,不如直接删除来的快。
2.x>=y 考虑一个比例 rate = x/y,这个也就是我们最多进行的+1操作次数,超过这个次数也不如直接删除来的更优.
那么假设我们现在枚举的gcd为质数p,那么对于一个数范围的区间 (k*p,(k+1)*p) ,在这个区间内肯定存在某个临界点,该点左面所有点全部删除,该点右面所有的值一直加到 (k+1)*p,来使得答案最优.
由上面我们所说的,rate为最多的加1的操作次数,那么给定区间我们可以计算出临界点为:
fen = ((k+1)*prime[i]-rate-1,k*prime[i])。
需要定义几个数组:
num[i] 小于等于i的数的个数
sum[i] 小于等于i的数的和.
复杂度:
枚举每个gcd,然后每次按照区间来处理, 对于每一个gcd最多有N/gcd 个区间. N为数的最大值
所以复杂度近似一个调和级数 NlogN
#include<bits/stdc++.h>using namespace std;const int maxn = 2e6+10;typedef long long ll;const ll inf = 1e15;int prime[maxn] = {0};bool vis[maxn] ={1,1};ll sum[maxn];int num[maxn];ll n,x,y,cnt=0;void init(){for(int i = 2;i < maxn ;i++){if(!vis[i]){prime[cnt++] = i;}for(int j=0;j < cnt && (ll)i*prime[j] < maxn ;j++){vis[i*prime[j]]=1;if(i % prime[j] == 0)break;}}}int main(){init();while(cin>>n>>x>>y){memset(sum,0,sizeof sum);memset(num,0,sizeof num);int a;int ma = 0;for(int i=1;i<=n;i++){ scanf("%d",&a); num[a]++; sum[a] += a; ma =max(a,ma);}for(int i=1;i <= 2*ma;i++){num[i] += num[i-1];sum[i] += sum[i-1];}ll rate = x/y;ll ans = inf;for(int i = 0;i < cnt && prime[i-1] <= ma;i++){ ll res = 0;for(int j=0;j*prime[i] <= ma;j++){ll fen = max((ll)j*prime[i],(ll)(j+1)*prime[i]-rate-1);ll delnum = num[fen] - num[j*prime[i]];//计算有多少个数要被删除 ll addsum = sum[(j+1)*prime[i]]-sum[fen];//计算要加1的数的和. ll addnum = num[(j+1)*prime[i]] - num[fen];//计算有多少个数要+1. ll cons = addnum*(j+1)*prime[i] - addsum;//加完以后的和-没加之前的和,为需要加几次 res += cons*y + delnum*x;//计算. if(res > ans) break;}ans = min (ans,res);}printf("%lld\n",ans);}return 0;}
阅读全文
0 0
- codeforces 580B Arpa and a list of numbers 前缀和+思维+分块 (调和级数)
- Codeforces 851D Arpa and a list of numbers【思维+前缀和】
- Codeforces 851 D Arpa and a list of numbers(前缀和)
- codeforces 851 D. Arpa and a list of numbers(前缀和+bruteforce)
- codeforces 850B Arpa and a list of numbers
- Codeforces Round #432 B. Arpa and a list of numbers
- Codeforces Round #432 -思维&素数筛魔改-D-Arpa and a list of numbers
- Codeforces Round #432 (Div. 1): B. Arpa and a list of numbers
- Codeforces Round #432 (Div. 2) D 850B Arpa and a list of numbers(gcd 枚举)
- Codeforces Round #432 (Div. 1) B. Arpa and a list of numbers
- Codeforces 851D. Arpa and a list of numbers
- Codeforces 432 Div. 2-D-Arpa and a list of numbers(枚举倍数求GCD)
- Codeforces 851 D. Arpa and a list of numbers(技巧)
- Codeforces 851D Arpa and a list of numbers (枚举+分段)
- CF850B-Arpa and a list of numbers
- CF_850B Arpa and a list of numbers
- Codeforces851D Arpa and a list of numbers(素数筛)
- Codeforces Round #432 (Div. 2) D. Arpa and a list of numbers E. Arpa and a game with Mojtaba
- unbuntu14 安装vim8 from-source
- Sql开发技巧
- 制作基于XKT-510和T3168芯片的无线供电模块
- 自符串的全排列
- C位级操作2
- codeforces 580B Arpa and a list of numbers 前缀和+思维+分块 (调和级数)
- VS2015 Warning LNK4221
- Cookie
- [JAVA]③取消窗体标题栏和无边框效果,可鼠标移动窗体
- 会话控制(session与cookie)
- ORACLE SEQUENCE用法
- 数组中次数超过一半的数字
- Jenkins job 之间实现带参数触发
- 欧拉函数板子