Codeforces 851 D Arpa and a list of numbers(前缀和)

来源:互联网 发布:matlab求协方差矩阵 编辑:程序博客网 时间:2024/05/20 07:35

题目地址
题意:你有2种操作,用最小的代价使得给定的序列为空或者gcd>1。

  • 操作1:删除一个点的代价为x
  • 操作2:让当前数+1的代价为y

思路:枚举每个数为最后gcd的数所需要的代价。因为有两种代价,如果这个数变成所需要成的数的代价大于x的话还不如删除。所以我们先计算出最多改变多少次,也就是最多可以比想要的数小cs。然后去算出代价就好了。算代价就用前缀和的思想,定义2个数组,一个记录比当前数小于等于的数有多少个,另一个记录比当前数小于等于的数总和为多少。 这样的话如果代价小于cs这些数就可以乘以y其他的就是乘以x。这样就是当前gcd的结果条件下最小的代价。

#include <iostream>#include <cstring>#include <string>#include <queue>#include <vector>#include <map>#include <set>#include <stack>#include <cmath>#include <cstdio>#include <algorithm>#include <iomanip>#define N 2000005#define M 4000010#define LL __int64#define inf 0x7f7f7f7f#define lson l,mid,ans<<1#define rson mid+1,r,ans<<1|1#define getMid (l+r)>>1#define movel ans<<1#define mover ans<<1|1using namespace std;const double PI = acos(-1.0);LL num[N], sum[N];int main() {    cin.sync_with_stdio(false);    LL n, m, x, y;    while (cin >> n >> x >> y) {        memset(num, 0, sizeof(num));        memset(sum, 0, sizeof(sum));        for (int i = 0; i < n; i++) {            cin >> m;            num[m]++;            sum[m] += m;        }        for (LL i = 1; i < N; i++) {            num[i] += num[i - 1];            sum[i] += sum[i - 1];        }        LL cs = (x + y - 1) / y;        LL ans = n*x;        for (LL i = 2; i < N; i++) {//枚举每个因子            LL cnt = 0;            for (LL j = i; j < N&&cnt < ans; j += i) {                LL k = max(j - i, j - cs);                cnt += ((num[j] - num[k])*j - (sum[j] - sum[k]))*y + (num[k] - num[j - i])*x;            }            ans = min(ans, cnt);        }        cout << ans << endl;    }    return 0;}
阅读全文
0 0