codeforces 850B Round #432 Div2D & Div1B:数论+计数
2017-09-05 17:59
471 查看
题意:给出n(<=5e5)个数字,每个数字在[ 1 , 1e6 ]范围内,定义bad为:1、序列非空;2、所有数字的GCD=1.现在有两种操作:1、删除某个数字,花费是x。2、给某个数字+1,花费为y,一个数字可以被加很多次。请求出让这个序列变成good(非bad)的最小花费。
题解:又是一个计数的问题。显然,我们希望得到GCD!=1,那么我们只需要枚举每个质数,让他作为GCD算最小花费,然后取最优即可。
一个显然的思路是,在1e6范围内进行素数筛,枚举素数,然后枚举每个数字,有两种方案:删掉(花费是x)、把他续了(花费是((ai+GCD-1)/GCD*GCD-ai)*y)。但是估计一下复杂度发现,复杂度是 素数个数*n的。但是1e6范围内有好几万个素数,然后愉快的TLE.
那么既然这个思路TLE了。我们就不能红果果的去算总花费,需要用一定的计数技巧。常用的方法是:每个数字遍历一遍来计数很慢,那如果可以一段区间一起计数就可以很快了。那么我们观察,当枚举一个素数GCD之后,每个数字有两种方案,删掉(x),续了(k*y),而且k*GCD这样的数字代价为0,于是我们考虑一个区间里边的数字[ k*GCD+1 , (k+1)*GCD-1 ],这个区间里边的每个数字都会得到一个花费。显然数字小的,删掉只需要x,如果续的话需要很多次y,那么小的数字删掉比较优,大的数字续了比较优。中间会有一个临界点,这个临界点就是K=x/y,某个数字a,最小的比他大的GCD的倍数是P,那么如果P-a<=k的话,把他续了比把他删了更优,相反如果P-a>k那么把他删了更优,于是我们可以用这种方法对落在长度为GCD-1区间内的数字一次性处理完毕。然后总区间长度是1e6,所以复杂度是1e6*(1/p1
+1/p2 +……+1/px)复杂度小于mlogm(m=1e6).
细节:对于区间前半段,我们直到删掉他们更优,于是我们只需要知道 ,某段区间内的数字个数有几个,这个可以用一个前缀和得到。
对于去见后半段,我们需要知道这些数字和(k+1)*GCD的差值的和,也就是∑((k+1)*GCD-ai)*y。假设总共有d个ai。那么可以化为(d*(k+1)*GCD-∑ai)*y。这个个数d可以通过前边那个前缀和得到。后边这个∑ai可以通过另外一个前缀和得到。
Code:
题解:又是一个计数的问题。显然,我们希望得到GCD!=1,那么我们只需要枚举每个质数,让他作为GCD算最小花费,然后取最优即可。
一个显然的思路是,在1e6范围内进行素数筛,枚举素数,然后枚举每个数字,有两种方案:删掉(花费是x)、把他续了(花费是((ai+GCD-1)/GCD*GCD-ai)*y)。但是估计一下复杂度发现,复杂度是 素数个数*n的。但是1e6范围内有好几万个素数,然后愉快的TLE.
那么既然这个思路TLE了。我们就不能红果果的去算总花费,需要用一定的计数技巧。常用的方法是:每个数字遍历一遍来计数很慢,那如果可以一段区间一起计数就可以很快了。那么我们观察,当枚举一个素数GCD之后,每个数字有两种方案,删掉(x),续了(k*y),而且k*GCD这样的数字代价为0,于是我们考虑一个区间里边的数字[ k*GCD+1 , (k+1)*GCD-1 ],这个区间里边的每个数字都会得到一个花费。显然数字小的,删掉只需要x,如果续的话需要很多次y,那么小的数字删掉比较优,大的数字续了比较优。中间会有一个临界点,这个临界点就是K=x/y,某个数字a,最小的比他大的GCD的倍数是P,那么如果P-a<=k的话,把他续了比把他删了更优,相反如果P-a>k那么把他删了更优,于是我们可以用这种方法对落在长度为GCD-1区间内的数字一次性处理完毕。然后总区间长度是1e6,所以复杂度是1e6*(1/p1
+1/p2 +……+1/px)复杂度小于mlogm(m=1e6).
细节:对于区间前半段,我们直到删掉他们更优,于是我们只需要知道 ,某段区间内的数字个数有几个,这个可以用一个前缀和得到。
对于去见后半段,我们需要知道这些数字和(k+1)*GCD的差值的和,也就是∑((k+1)*GCD-ai)*y。假设总共有d个ai。那么可以化为(d*(k+1)*GCD-∑ai)*y。这个个数d可以通过前边那个前缀和得到。后边这个∑ai可以通过另外一个前缀和得到。
Code:
#include<bits/stdc++.h> using namespace std; const int MAX = 5e5+100; const int MAXX = 2e6+100; int prime[MAXX]; int a[MAX]; int sum1[MAXX]; long long sum2[MAXX]; bool vis[MAXX]; int tot; int n,x,y; long long ans = 0x3f3f3f3f3f3f3f3fLL; void input(){ scanf("%d%d%d",&n,&x,&y); for (int i=0;i<n;i++){ scanf("%d",a+i); sum1[a[i]]++; sum2[a[i]]+=a[i]; } } void init(){ for (int i=1;i<=2e6;i++){ sum1[i]+=sum1[i-1]; sum2[i]+=sum2[i-1]; } for (int i=2;i<=1e6;i++){ if (!vis[i]){ prime[tot++] = i; vis[i] = true; } for (int j=0;j<tot;j++){ int temp = i*prime[j]; if (temp>1e6){ break; } vis[temp] = true; } } } void solve(){ for (int i=0;i<tot;i++){ long long res =0; int P = prime[i]; int k = min(x/y,P-1); for (int j=0;j<=1e6;j+=P){ res+=1LL*(sum1[j+P-k-1]-sum1[j])*x; res+=(1LL*(sum1[j+P-1]-sum1[j+P-k-1])*(j+P)-sum2[j+P-1]+sum2[j+P-k-1])*y; } ans = min(ans,res); } printf("%I64d\n",ans); } int main(){ input(); init(); solve(); return 0; }
相关文章推荐
- codeforces#232_div2_C On Number of Decompositions into Multipliers 数论 组合计数
- codeforces#232_div2_C On Number of Decompositions into Multipliers 数论 组合计数
- Codeforces 456 div2 A B ***D(思维题) ***E(二分/DFS/数论)
- Codeforces Round #424 (Div. 2, rated, based on VK Cup Finals) Problem F (Codeforces 831F) - 数论 - 暴力
- [数论] 51Nod 1217 Minimum Modular & Codeforces 303C #183 (Div. 1) Minimum Modular
- CodeForces 3107 ODDDIV - Odd Numbers of Divisors(数论)
- CodeForces 369 div2 D Directed Roads 图论 数论
- CodeForces 369 div2 E. ZS and The Birthday Paradox 数论
- Codeforces 869C Round #439 Div2 C:排列组合计数
- Codeforces Round #425 (Div. 2) Problem C Strange Radiation (Codeforces 832C) - 二分答案 - 数论
- [数论] Codeforces Round #324 (Div. 2)D. Dima and Lisa
- Codeforces 78C Beaver Game(数论、博弈)
- 交换a串的位置让b.c串出现最多次 暴力 Codeforces Div. 2 B. ZgukistringZ
- 【Codeforces Round #398 (Div. 2)】Codeforces 767D Cartons of milk
- Codeforces 406(div2)
- 数论初步———codeforces 787AA The Monster
- POJ 2154 Color(组合数学-波利亚计数,数论-欧拉函数,整数快速幂)
- codeforces 848B :计数
- [Codeforces]Codeforces Round #460 (Div. 2)
- codeforces 260 div2 C题