Codeforces 1603D. Artistic Partition

Codeforces 1603D. Artistic Partition

看到题目很容易列出一个 \(\text{DP}\) 的转移式: ( 此处 \(f(k,n)\) 为题目中的 \(f(n,k)\) )

\[f(k,\,i)=\min_{1\le j\le i}\{f(k-1,\,j-1)+c(j,\,i)\} \]

由于直接算 \(c(l,\,r)\)\(\mathcal O(n^2\log n)\) 的, 直接暴力 \(\text{DP}\)\(\mathcal O(n^5\log n)\) 的. 考虑优化.

首先可以考虑推式子优化 \(c(l,\,r)\) 的计算过程.

\[\begin{align*} c(l,\,r)&=\sum_{i=l}^r\sum_{j=i}^r[\,\gcd(i,j)\ge l\,]\\&=\sum_{d=l}^r\sum_{i=l}^r\sum_{j=i}^r[\,\gcd(i,j)=d\,]\\&=\sum_{d=l}^r\sum_{i=1}^{\left\lfloor\frac{r}{d}\right\rfloor}\sum_{j=i}^{\left\lfloor\frac{r}{d}\right\rfloor}[\,\gcd(i,j)=1\,]\\&=\sum_{d=l}^r\sum_{i=1}^{\left\lfloor\frac{r}{d}\right\rfloor}\varphi(i)\\&=\sum_{d=l}^rp\left({\left\lfloor\frac{r}{d}\right\rfloor}\right) \end{align*} \]

其中 \(p(n)=\sum\limits_{i=1}^n\varphi(i)\) . 预处理出 \(\varphi(i)\) 就可以做到 \(\mathcal O(n)\) 查询 \(c(l,\,r)\) . 考虑固定右端点 \(r\) , 易知 \(\left\lfloor\dfrac{r}{d}\right\rfloor\) 只有 \(2\sqrt{n}\) 种不同的取值. 因此可以做到 \(\mathcal O(\sqrt n)\) 查询 \(c(l,\,r)\) . 现在就可以做到 \(\mathcal O(n^3\sqrt{n})\)\(\text{DP}\) 转移.

接着发现: \(f(k,\,i)\ge i,\,\)\(\forall y\in [\,x,\,2x-1\,],\ c(x,\,y)=y-x+1\) . 于是当 \(k>\log n\) 时, 存在最优的策略为 \(f(k,\,n)\ge\sum\limits_{i\ge 0}c(2^i,\,2^{i+1}-1)=n\) . 因此我们把 \(k\) 那一维降到了 \(\log n\) 级别, 于是现在的 \(\text{DP}\) 转移为 \(\mathcal O(n^2\sqrt{n}\log n)\) . 但这还远远不够.

注意到题目多测, 而有用的状态不超过 \(\mathcal O(n\log n)\) , 于是可以预处理, 把所有有用的状态记录下来, 然后多测时 \(\mathcal O(1)\) 回答.

现在要求的就是这个 \(\text{DP}\) 数组 \(f(k,\,n)\) , 其中 \(k\le \log n\) . 转移式为

\[f(k,\,i)=\min_{1\le j\le i}\{f(k-1,\,j-1)+c(j,\,i)\} \]

观察到这个转移式一脸可以决策单调性优化的样子. 于是考察 \(c(l,\,r)\) 是否满足四边形不等式.

引理 1 二元函数 \(c(l,\,r)\) 满足四边形不等式, 即 \(\forall i<j\le k<l,\ \mathrm{s.t.}\ c(i,\,k)+c(j,\,l)\le c(i,\,l)+c(j,\,k)\) .

证明\(q(i,\,j,\,r)=\sum\limits_{k=i}^jp\left(\left\lfloor\dfrac{r}{k}\right\rfloor\right)\) . 于是有

\[\begin{align*} c(i,\,l)+c(j,\,k)&=q(i,\,l,\,l)+q(j,\,k,\,k)\\&=(q(i,\,j-1,\,l)+q(j,\,l,\,l))+(q(i,\,k,\,k)-q(i,\,j-1,\,k))\\&=q(i,\,j-1,\,l)+c(j,\,l)+c(i,\,k)-q(i,\,j-1,\,k)\\&=c(i,\,k)+c(j,\,l)+(q(i,\,j-1,\,l)-q(i,\,j-1,\,k)) \end{align*} \]

又因为 \(l\ge k\) , 因此有 \(q(i,\,j-1,\,l)\ge q(i,\,j-1,\,k)\) . 于是 \(c(i,\,l)+c(j,\,k)\ge c(i,\,k)+c(j,\,l)\) . 证毕

于是我们就可以用分治去优化这个决策单调 \(\text{DP}\) 的转移.

由于查询 \(c(l,\,r)\)\(\mathcal O(\sqrt n)\) 的, 分治一次的时间复杂度为 \(T(n)=2T\left(\dfrac{n}2\right)+\mathcal O(n\sqrt{n})\) , 即 \(\mathcal O(n\sqrt n)\) . 一共要执行 \(k=\log n\)\(\text{DP}\) 的转移, 于是总时间复杂度为 \(\mathcal O(n\sqrt{n}\log n)\) . 实际情况跑得飞快.

参考代码
#include <bits/stdc++.h>
using namespace std;
static constexpr int64_t inf = 0x3f3f3f3f3f3f3f3f;
static constexpr int Maxn = 1e5 + 5, Maxk = 18;
int phi[Maxn], sphi[Maxn];
void sieve_phi(int N, int *phi) {
  for (int i = 1; i <= N; ++i) phi[i] = i;
  for (int i = 2; i <= N; ++i)
    if (phi[i] == i)
      for (int j = i; j <= N; j += i)
        phi[j] -= phi[j] / i;
} // sieve_phi
int64_t calc_w(int l, int r) {
  if (l > r) return inf;
  int64_t ans = 0;
  for (int i = l, j, x; i <= r; i = j + 1) {
    j = r / (r / i); x = 0;
    if (i >= l) x = j - i + 1;
    else if (j >= l) x = j - l + 1;
    ans += sphi[r / i] * x;
  }
  return ans;
} // calc_w (s.t. quadrangle inequality)
void divide(int64_t *prv, int64_t *cur, int l, int r, int opt_l, int opt_r) {
  if (l > r) return ;
  int mid = (l + r) >> 1, opt = opt_l;
  int64_t cost = calc_w(min(mid, opt_r) + 1, mid), w;
  cur[mid] = inf;
  for (int k = min(mid, opt_r); k >= opt_l; cost = calc_w(k--, mid))
    if ((w = prv[k] + cost) <= cur[mid]) cur[mid] = w, opt = k;
  divide(prv, cur, l, mid - 1, opt_l, opt);
  divide(prv, cur, mid + 1, r, opt, opt_r);
} // divide
int main(void) {
  static constexpr int N = 1e5, K = 17;
  sieve_phi(N, phi); sphi[0] = 0;
  for (int i = 1; i <= N; ++i) sphi[i] = sphi[i - 1] + phi[i];
  static int64_t f[Maxk][Maxn];
  memset(f, inf, sizeof(f)); f[0][0] = 0;
  for (int i = 1; i <= N; ++i) f[1][i] = (int64_t)i * (i + 1) / 2;
  for (int k = 2; k <= K; ++k) divide(f[k - 1], f[k], 1, N, 1, N);
  int tests; scanf("%d", &tests);
  while (tests--) {
    int n, k; scanf("%d%d", &n, &k);
    printf("%lld\n", (k >= Maxk || (1 << k) > n) ? n: f[k][n]);
  }
  exit(EXIT_SUCCESS);
} // main
posted @ 2021-11-12 20:16  cutx64  阅读(61)  评论(0)    收藏  举报