Codeforces Round #432 (Div. 1) B. Arpa and a list of numbers

qtmd的复习pat,老子不想看了,还不如练几道cf

这题首先可以很容易想到讨论最后的共因子为素数
这个素数太多了,1-1e6之间的素数
复杂度爆炸
所以使用了前缀和,对于每个素数k的每个小区间
(kg, k(g + 1)]是可以直接求这个区间的最佳方案的

#include<iostream>
#include<map>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<set>
#include<vector>
#include<queue>
#include<stack>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 1e6+5;
#define MS(x,y) memset(x,y,sizeof(x))
#define MP(x, y) make_pair(x, y)
const int INF = 0x3f3f3f3f;

ll sum[N];
int cnt[N];
int isprime[N];

int j;
ll Sum(int x) {
    if(x <= j) return sum[j];
    else if(x >= N) return sum[N-1];
    else return sum[x]; 
}
int Cnt(int x) {
    if(x <= j) return cnt[j];
    else if(x >= N) return cnt[N-1];
    else return cnt[x];
}
int main() {
    int n, x, y;
    while(~scanf("%d %d %d", &n, &x, &y)) {
        int ed = x/y; 
        for(int i = 0; i < n; ++i) {
            int a; scanf("%d", &a);
            sum[a] += a;
            cnt[a] ++;
        }
        for(int i = 1; i < N; ++i) {
            sum[i] += sum[i-1];
            cnt[i] += cnt[i-1];
        }
        ll ans = 1e18;

        for(int i = 2; i < N; ++i) {
            if(!isprime[i]) {
                ll tmp = 0;
                for(j = 0; j < N; j += i) {
                    isprime[j] = 1;

                    int fr1 = j + i - 1; int to1 = j + i - ed - 1;   int fr2 = j + i - ed - 1; int to2 = j;

                    ll t1 = Sum(fr1) - Sum(to1); int t2 = Cnt(fr1) - Cnt(to1);
                    int t3 = Cnt(fr2) - Cnt(to2);
                //  if(i == 17 && j < 20) printf("%d %lld %d %d %lld
", j, t1, t2, t3, tmp);

                    tmp += 1ll*(1ll*t2*(j+i) - t1) * y + 1ll* t3 * x;
                }
                ans = min(ans, tmp);
            }
        }
        printf("%lld
", ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/Basasuya/p/8433689.html