CodeForces 623B【质因子预处理+DP】

来源:互联网 发布:大数据 书 编辑:程序博客网 时间:2024/05/03 04:23

题意:
给出n,a,b以及n个整数a1,a2…an, 可以对数组进行以下两种操作;
(1)花费len*a的代价删除连续的len个数,len<|S|
(2)花费b的代价将某一个a[i]加一或减一
每个数最多执行一次这样的操作;
使得这个数组所有数的GCD>1;
求最小花费;
思路:
因为删除操作不能一下子删完,所以肯定会剩下一个,那么就会是头一个或者最后一个。所以剩下的数可能有a[1]-1,a[1]+1,a[1],a[n],a[n]-1,a[n]+1。
预处理出所有数的质因子,枚举每个质因子之间默认就是整个数组的公约数.
DP:
[不变] 只能前面存在不变 或者 +/-过
[删除] 要么是从来都没有变过 开始删除, 要么是已经删除过了,继续删除
[+/- ] 前面能存在删除 或者 不变 或者 +/-过

#include<bits/stdc++.h>using namespace std;typedef long long LL;const int N = 1e6+10;const LL INF = 1e18;LL dp[N][3];    //0: 不变; 1: +1/-1; 2: 删除LL val[N];LL a, b;int n;vector<LL>gcd;void init(LL x){    for(LL i = 2;i * i <= x;i++){        if(x % i == 0) gcd.push_back(i);        while(x % i ==0) x /= i;    }    if(x != 1) gcd.push_back(x);}LL solve(LL g){    LL temp;    dp[0][0] = dp[0][1] = dp[0][2] = 0;    for(int i=1;i<=n;i++){        temp = 1e18;        if((val[i] + 1) % g == 0 || (val[i] - 1) % g == 0) temp = b;        if(val[i] % g == 0) temp = 0;        dp[i][0] = dp[i-1][0] + temp;dp[i][0] = min(dp[i][0], INF);        dp[i][2] = min(dp[i-1][1], dp[i-1][2]) + temp;dp[i][2] = min(dp[i][2], INF);        dp[i][1] =  min(dp[i-1][0], dp[i-1][1]) + a;dp[i][1] = min(dp[i][1], INF);    }     return min(dp[n][0],min(dp[n][1],dp[n][2]));}int main(){    scanf("%d%I64d%I64d", &n, &a, &b);    for(int i=1;i<=n;i++)        scanf("%I64d", &val[i]);    gcd.clear();    init(val[1]);    init(val[1] + 1);    init(val[1] - 1);    init(val[n]);    init(val[n] + 1);    init(val[n] - 1);    sort(gcd.begin(), gcd.end());    gcd.erase(unique(gcd.begin(), gcd.end()), gcd.end());    LL ans = 2e18;    for(int i=0;i<gcd.size();i++){        ans = min(solve(gcd[i]), ans);    }    printf("%I64d\n", ans);    return 0;}