Codeforces 题面传送门 & 洛谷题面传送门

学 whk 时比较无聊开了道题做做发现是道神题(

介绍一种不太一样的做法,不观察出决策单调性也可以做。

首先一个很 trivial 的 observation 是,如果 \(2^{k-1}>n\)​ 那么答案就是 \(n\)​,因为我们可以第 \(i\) 段放 \(2^{i-1}\) 个数(最后一段除外),这样每一段中,肯定只有形如 \((x,x)\) 的整数对会产生贡献,这样答案刚好取到下界 \(n\)。

我们设 \(dp_{i,j}\) 表示前 \(i\) 个数分成 \(j\) 段,它们的 \(f\) 值之和的最小值,显然 \(j\) 的上界只用取到 \(18\),因此我们计算出 \(dp_{i,j}\) 之后即可 \(\Theta(1)\) 地求出答案。至此,问题转化为如何求 \(dp_{i,j}\)。

考虑化简 \(c(l,r)\) 的表达式,一个非常浅显的性质是对于 \(\min(i,j)<l\) 的数对 \((i,j)\),必然有 \(\gcd(i,j)<l\),因此我们可以直接那拿总数 \(\dfrac{r(r+1)}{2}\) 减去 \(\gcd(i,j)\) 小于 \(l\) 的数对 \((i,j)\) 的个数,即如果我们设 \(g(n,k)=\sum\limits_{i=1}^n\sum\limits_{j=i}^n[\gcd(i,j)\le k]\),那么有 \(dp_{i,j}=\min\limits_{k}dp_{k,j-1}+\dfrac{i(i+1)}{2}-g(i,k)\)。而根据莫比乌斯反演的知识,有

\[\begin{aligned}
g(n,k)&=\sum\limits_{i=1}^n\sum\limits_{j=1}^n[\gcd(i,j)\le k]\\
&=\sum\limits_{d=1}^k\sum\limits_{i=1}^n\sum\limits_{j=i}^n[\gcd(i,j)=d]\\
&=\sum\limits_{d=1}^k\sum\limits_{i=1}^{n/d}\sum\limits_{j=i}^{n/d}[\gcd(i,j)=1]\\
&=\sum\limits_{d=1}^k\dfrac{1+\sum\limits_{p=1}^{n/d}\mu(p)\lfloor\dfrac{n}{dp}\rfloor^2}{2}
\end{aligned}
\]

考虑怎样维护之,也就是说怎样动态地对于一个决策点 \(k\),用个什么东西维护 \(dp_{k,j-1}-g(i,k)\) 的值,进而求出全局最小值。考虑线段树优化 dp。我们建立一棵线段树,并且希望,当我们动态地枚举到 \(i\) 时,线段树上下标为 \(k\) 的位置上的值就等于 \(dp_{k,j-1}-g(i,k)\),那么就有 \(dp_{i,j}=\dfrac{i(i+1)}{2}+\text{此时线段树上全局最小值}\)。

这又该怎样维护呢?我们发现这样一个性质:当 \(n\) 由 \(n-1\) 变到 \(n\) 时,只有那些 \(d\mid n\) 的 \(\sum\limits_{p=1}^{n/d}\mu(p)\lfloor\dfrac{n}{dp}\rfloor^2\) 会发生改变,也就是说,对于一个固定的 \(k\),如果我们预处理出了 \(sum_i=\sum\limits_{i=1}^n\mu(i)\lfloor\dfrac{n}{i}\rfloor\),那么我们可以在 \(\Theta(d(n))\) 的时间内计算出 \(g(n,k)-g(n-1,k)\)。具体方法就是,遍历所有 \(d\mid n\),如果 \(d\le k\),那么就会 \(g(n,k)\) 就会相较于 \(g(n-1,k)\) 产生 \(\dfrac{1+\sum\limits_{p=1}^{n/d}\mu(p)\lfloor\dfrac{n}{dp}\rfloor^2}{2}-\dfrac{1+\sum\limits_{p=1}^{(n-1)/d}\mu(p)\lfloor\dfrac{n-1}{dp}\rfloor^2}{2}\) 的增量。发现了这个性质以后就很好维护了,当我们扫描到 \(i\) 时遍历一遍所有 \(i\) 的因子 \(d\),计算出 \(\dfrac{1+\sum\limits_{p=1}^{i/d}\mu(p)\lfloor\dfrac{i}{dp}\rfloor^2}{2}-\dfrac{1+\sum\limits_{p=1}^{(i-1)/d}\mu(p)\lfloor\dfrac{i-1}{dp}\rfloor^2}{2}\),然后在线段树上执行一遍后缀减即可。

时间复杂度 \(n\ln n\log^2n\),较为卡常。

using namespace fastio;
const int MAXV = 1e5;
const int LOG_N = 18;
const int MAXC = MAXV << 4;
int pr[MAXV / 6 + 5], mu[MAXV + 5], prcnt = 0;
int smu[MAXV + 5]; ll sm[MAXV + 5];
bool vis[MAXV + 5];
int hd[MAXV + 5], val[MAXC + 5], nxt[MAXC + 5], item_n = 0;
void ins(int x, int y) {val[++item_n] = y; nxt[item_n] = hd[x]; hd[x] = item_n;}
void sieve(int n) {
mu[1] = 1;
for (int i = 2; i <= n; i++) {
if (!vis[i]) mu[i] = -1, pr[++prcnt] = i;
for (int j = 1; j <= prcnt && pr[j] * i <= n; j++) {
vis[pr[j] * i] = 1; if (i % pr[j] == 0) break;
mu[pr[j] * i] = -mu[i];
}
}
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j += i)
ins(j, i);
for (int i = 1; i <= n; i++) smu[i] = smu[i - 1] + mu[i];
for (int i = 1; i <= n; i++) {
sm[i] = sm[i - 1];
for (int e = hd[i]; e; e = nxt[e]) {
int f = val[e];
sm[i] -= 1ll * mu[f] * (i / f - 1) * (i / f - 1);
sm[i] += 1ll * mu[f] * (i / f) * (i / f);
}
}
}
ll dp[LOG_N + 2][MAXV + 5];
struct node {ll mn, lz;} s[MAXV * 4 + 5];
void pushup(int k) {s[k].mn = min(s[k << 1].mn, s[k << 1 | 1].mn) + s[k].lz;}
void build(int k, int l, int r, int lv) {
s[k].lz = 0; if (l == r) return s[k].mn = 2 * dp[lv][l], void();
int mid = l + r >> 1; build(k << 1, l, mid, lv); build(k << 1 | 1, mid + 1, r, lv);
pushup(k);
}
void tag(int k, ll v) {s[k].lz += v; s[k].mn += v;}
void modify(int k, int l, int r, int p, ll v) {
if (l >= p) return tag(k, v), void();
int mid = l + r >> 1;
if (p <= mid) modify(k << 1, l, mid, p, v), tag(k << 1 | 1, v);
else modify(k << 1 | 1, mid + 1, r, p, v);
pushup(k);
}
int main() {
sieve(MAXV); memset(dp, 0x1f, sizeof(dp)); dp[0][0] = 0;
for (int i = 1; i <= MAXV; i++) dp[1][i] = 1ll * i * (i + 1) / 2;
for (int i = 2; i <= LOG_N; i++) {
build(1, 0, MAXV, i - 1);
for (int j = 1; j <= MAXV; j++) {
for (int e = hd[j]; e; e = nxt[e]) {
int f = val[e];
ll ori = ((j / f == 1) ? 0 : 1) + sm[j / f - 1];
ll cur = 1 + sm[j / f];
modify(1, 0, MAXV, f, ori - cur);
}
dp[i][j] = ((s[1].mn + s[1].lz) / 2) + 1ll * j * (j + 1) / 2;
// printf("%d %d %lld\n", i, j, dp[i][j]);
}
}
int qu; read(qu);
while (qu--) {
int n, k; read(n); read(k);
if (k > LOG_N) print(n, '\n');
else print(dp[k][n], '\n');
}
print_final();
return 0;
}

Codeforces 1603D - Artistic Partition(莫反+线段树优化 dp)的更多相关文章

  1. Codeforces Round #426 (Div. 2) D 线段树优化dp

    D. The Bakery time limit per test 2.5 seconds memory limit per test 256 megabytes input standard inp ...

  2. D - The Bakery CodeForces - 834D 线段树优化dp···

    D - The Bakery CodeForces - 834D 这个题目好难啊,我理解了好久,都没有怎么理解好, 这种线段树优化dp,感觉还是很难的. 直接说思路吧,说不清楚就看代码吧. 这个题目转 ...

  3. BZOJ2090: [Poi2010]Monotonicity 2【线段树优化DP】

    BZOJ2090: [Poi2010]Monotonicity 2[线段树优化DP] Description 给出N个正整数a[1..N],再给出K个关系符号(>.<或=)s[1..k]. ...

  4. [AGC011F] Train Service Planning [线段树优化dp+思维]

    思路 模意义 这题真tm有意思 我上下楼梯了半天做出来的qwq 首先,考虑到每K分钟有一辆车,那么可以把所有的操作都放到模$K$意义下进行 这时,我们只需要考虑两边的两辆车就好了. 定义一些称呼: 上 ...

  5. 【bzoj3939】[Usaco2015 Feb]Cow Hopscotch 动态开点线段树优化dp

    题目描述 Just like humans enjoy playing the game of Hopscotch, Farmer John's cows have invented a varian ...

  6. POJ 2376 Cleaning Shifts (线段树优化DP)

    题目大意:给你很多条线段,开头结尾是$[l,r]$,让你覆盖整个区间$[1,T]$,求最少的线段数 题目传送门 线段树优化$DP$裸题.. 先去掉所有能被其他线段包含的线段,这种线段一定不在最优解里 ...

  7. 洛谷$P2605\ [ZJOI2010]$基站选址 线段树优化$dp$

    正解:线段树优化$dp$ 解题报告: 传送门$QwQ$ 难受阿,,,本来想做考试题的,我还造了个精妙无比的题面,然后今天讲$dp$的时候被讲到了$kk$ 先考虑暴力$dp$?就设$f_{i,j}$表示 ...

  8. 4.11 省选模拟赛 序列 二分 线段树优化dp set优化dp 缩点

    容易想到二分. 看到第一个条件容易想到缩点. 第二个条件自然是分段 然后让总和最小 容易想到dp. 缩点为先:我是采用了取了一个前缀最小值数组 二分+并查集缩点 当然也是可以直接采用 其他的奇奇怪怪的 ...

  9. 2021.12.08 P1848 [USACO12OPEN]Bookshelf G(线段树优化DP)

    2021.12.08 P1848 [USACO12OPEN]Bookshelf G(线段树优化DP) https://www.luogu.com.cn/problem/P1848 题意: 当农夫约翰闲 ...

随机推荐

  1. Java(21)内部类

    作者:季沐测试笔记 原文地址:https://www.cnblogs.com/testero/p/15228411.html 博客主页:https://www.cnblogs.com/testero ...

  2. NX Open 图层说

    我也是偶然发现的,在一次调试下,竟然会报警. 所以我写了测试代码,进行测试:结果如下 纳尼???还有271层?还能设置大于256层?NX open可以的.

  3. Mybatis初始化机制

    对于任何框架而言,在使用前都要进行一系列的初始化,MyBatis也不例外.本章将通过以下几点详细介绍MyBatis的初始化过程. 1.MyBatis的初始化做了什么 2. MyBatis基于XML配置 ...

  4. vue如何监听数组的变化

    export function def (obj: Object, key: string, val: any, enumerable?: boolean) { Object.defineProper ...

  5. 搬运3:welpwnctf题目

    记录一道自己做的ctf题目:welpwn --RCTF-2015 1.老生常谈checksec查看: 可以看到只开了nx保护,下面我们进入ida下面看看. 发现是一个想rbp-400,rsp+0h的地 ...

  6. 21.10.9 test

    T1 购票方案 \(\color{green}{100}\) 对于每个时间节点维护它作为每种票所能包含的最后一个点时,这种票的起始点位置,由于这个位置是单调的,所以类似双指针维护,\(O(KN)\) ...

  7. NOIP模拟86(多校19)

    T1 特殊字符串 解题思路 \(f_{i,j}\) 表示前 \(i\) 个字符中结尾为 \(j\) 的最大贡献. 转移枚举当前位置于之前位置结尾的组合加上贡献即可. 对于边界问题,容易发现选择 1 一 ...

  8. [转]DDR内存条rank的概念和区分

    1:什么是RANK? 答:CPU与内存之间的接口位宽是64bit,也就意味着CPU在一个时钟周期内会向内存发送或从内存读取64bit的数据.可是,单个内存颗粒的位宽仅有4bit.8bit或16bit, ...

  9. Luogu P1654 OSU! | 期望

    题目链接 很妙的一道题. 题目要求$X^3$的期望值. 直接求不好求. 考虑先求出$X$和$X^2$的期望值,然后再求$X^3$的期望值. 迎.刃.而.解. #include<iostream& ...

  10. 从零开始搭建你的nvim ide

    前言概述 vim由于其丰富的扩展性.出色的跨平台性.高效率的操作性深受一大批粉丝的追捧,甚至就连vim和emacs之间孰优孰劣的话题都能被引起一场编辑器之间的圣战,足以见vim是多么的优秀. vim的 ...