zoukankan      html  css  js  c++  java
  • CF623B Array GCD

    CF623B Array GCD

    给定一个序列 (a_i) ,可以进行一下两种操作:

    • 删除一段长度为 (m) 的区间 ((m<n)) ,花费为 (m imes A) ,只能操作一次
    • 可以花费 (b) 让一个元素 (+1)(-1) ,每个元素只能操作一次

    求使得剩下的数最大公约数大于 (1) 的最小花费

    (nleq10^6, a_{i}in[2, 10^9])

    贪心,动态规划


    由于删除的区间长度小于 (n) ,则最优解剩下的序列一定包含 (a_1)(a_n) ,则最后的 (gcd) 一定是 (a_1, a_1+1, a_1-1, a_n, a_n+1, a_n-1) 其中之一的约数

    由于每个数的不同质因子个数是 (log) 级别的,可以考虑枚举这 (6) 个数各自的质因子当作最大公约数

    当确定了 (gcd) ,考虑如何求出最小花费

    可以设计一个 dp,令 (f_{i, 0/1/2}) 为截至第 (i) 位,没有删除过区间 / 正在删除一段区间 / 已经删除了一段区间 所能得到的最小花费

    可以列出方程 (egin{cases}f_{i, 0}=f_{i-1, 0}+cost_i\f_{i, 1}=min(f_{i-1, 0}, f_{i-1, 1})+A\f_{i, 2}=min(f_{i-1, 1}, f_{i-1, 2})+cost_iend{cases})

    时间复杂度 (O(nlog n))

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    const int maxn = 1e6 + 10;
    ll f[3][maxn];
    int n, A, B, a[maxn];
    
    inline ll calc(int x, int P) {
      if (x % P == 0) return 0;
      if ((x + 1) % P == 0 || (x - 1) % P == 0) {
        return B;
      }
      return 1ll << 40;
    }
    
    inline ll check(int P) {
      bool flg = 1;
      f[1][0] = f[2][0] = 1ll << 40;
      for (int i = 1; i <= n; i++) {
        ll v = calc(a[i], P);
        f[0][i] = f[0][i - 1] + v;
        f[1][i] = min(f[0][i - 1], f[1][i - 1]) + A;
        f[2][i] = min(f[1][i - 1], f[2][i - 1]) + v;
        flg &= i == 1 || f[0][i - 1] > f[1][i - 1];
      }
      return min(f[0][n], min(flg ? 1ll << 60: f[1][n], f[2][n]));
    }
    
    inline ll factor(int x) {
      int tmp = sqrt(x);
      ll res = 1ll << 60;
      for (int i = 2; i <= tmp; i++) {
        if (x % i == 0) {
          res = min(res, check(i));
          while (x % i == 0) x /= i;
        }
      }
      if (x > 1) res = min(res, check(x));
      return res;
    }
    
    int main() {
      scanf("%d %d %d", &n, &A, &B);
      for (int i = 1; i <= n; i++) {
        scanf("%d", a + i);
      }
      if (n == 1) return puts("0");
      int s[7];
      s[1] = a[1];
      s[2] = a[1] - 1;
      s[3] = a[1] + 1;
      s[4] = a[n];
      s[5] = a[n] - 1;
      s[6] = a[n] + 1;
      ll ans = 1ll << 60;
      for (int i = 1; i < 7; i++) {
        ans = min(ans, factor(s[i]));
      }
      printf("%I64d", ans);
      return 0;
    }
    
  • 相关阅读:
    JS 百度地图路书---动态路线
    jQuery---创建和添加节点
    CSS基础
    第一篇:前端知识之HTML内容
    JS高级---为内置对象添加原型方法
    JS DOM属性+JS事件
    Vue-router
    vue使用kkfileview文件预览功能
    JS高级---案例:验证密码的强度
    promise是怎么来的?
  • 原文地址:https://www.cnblogs.com/Juanzhang/p/11001692.html
Copyright © 2011-2022 走看看