题解:CF438D The Child and Sequence
题目
思路
题目要求我们完成三种操作:
- 区间求和
- 区间取模
- 单点修改
1,3两种都非常简单,问题在于如何维护区间取模。
可以想到维护区间最大值,如果小于模数则不处理,否则将这个区间重新pushup。
如何证明该复杂度?注意到,一个数最多会被取模 $log{a_i}$ 次,所以复杂度我 $O(nlog_nlog{\max{a_i}})$ 。
代码
1 |
|
然而没有什么技巧。
题解:CF438D The Child and Sequence
题目要求我们完成三种操作:
1,3两种都非常简单,问题在于如何维护区间取模。
可以想到维护区间最大值,如果小于模数则不处理,否则将这个区间重新pushup。
如何证明该复杂度?注意到,一个数最多会被取模 $log{a_i}$ 次,所以复杂度我 $O(nlog_nlog{\max{a_i}})$ 。
1 |
|
然而没有什么技巧。
首先可以看出这是一道数位dp。它的参数分为两个部分:是否magic和是否是 $m$ 的倍数。这两个部分其实都比较好处理:前者在dfs是判断即可(这里并不复杂,其实直接从高位开始推就行了,不用考虑奇偶位不一样问题…),后者记录一下当前$\mod m$ 的余数,最后再判断。最后,因为字符串不好减一(其实也可以减),所以需要特判一下左端点字符串。
1 |
|
You have a square grid of size $m×m$. There are $n$ troops placed on this grid, each with coordinates $(x_i,y_i)$.
Over t minutes, the following events occur:
Move: A troop numbered x moves in a direction (up, down, left, or right) for d units. Troops cannot move outside the grid.
Regroup: Troop x gathers all other troops that share the same row or column as troop x. These troops move to troop x’s location.
The cost of moving troop $i$ to troop $j$ is calculated as: $(x_i−x_j)^2+(y_i−y_j)^2$.
For each regrouping event, output the total cost of all troop movements during that regrouping, modulo $10^9+7$.
我们对于每一个横坐标/纵坐标,记录下它们对应的纵坐标/横坐标(由于 $m$ 会很大,我们考虑把这些坐标离散化)。使用并查集,记录每一个士兵属于的块(即祖先节点),以及该块的大小。接下来开始操作。首先使用一个小技巧:对于每次操作,再开一个新点,这样就不用讨论该块的祖先节点是否改动。
对于操作1(对应下面操作S)非常好处理,将原来块大小减一,再将其放置到新快中;
对于操作2(对应下面操作Q),我们把当前士兵的位置作为新的块,依次遍历所有和它同行同列的块,这里要注意,对于与该士兵同样位置的士兵会在两次遍历中都被加入新块,要减一次。
想通这些部分,问题就迎刃而解了,只需模拟我们上述的思路即可。
Warnings:
要看2倍数组
要及时取模!中间会爆龙龙
1 |
|
做了我2d,纯纯可恶 (σ`д′)σ
题解:Black And White / Flip and Combos
题目描述
给你一个长度为n的01序列 a[1],…,a[n]
每次询问给定一个区间[l,r],询问[l,r]里最长的连续的1的长度
每次修改给定一个区间[l,r],将[l,r]里的a[i]变成1-a[i](或者说异或1)
n, m <= 100000
输入格式
第一行一个n
第二行n个数,表示01序列初始状态
第三行一个m,接下来m行,每行有三个数x,l,r
若 x=0,表示一次查询,查询[l,r]里的最长连续1的长度
若 x=1,表示一次修改,将[l,r]里的数异或1
输出格式
对于输入里的每一个查询,输出一行一个整数,该询问的最长连续1的长度
维护最长子串是经典的线段树,由于有01翻转修改,所以不能只存连续1串,也要存0.
思路可能和GSS有点像,都是维护区间最长前缀、后缀和子串(GSS是子序列),修改就翻转+重新pushup就行了。
其实不是很困难,但是线段树写起来非常易错(因为我很菜orz)
1 |
|
撒花!
题解:洛谷P6279 [USACO20OPEN] Favorite Colors G
被for(auto a:b)背刺了/fn/fn
使用并查集和启发式合并
由题意我们可以很显然地发现一个节点的子节点颜色一样,同理,这些子节点的所有子节点颜色都一样,这时,我们可以把这些子节点全部合并到一个节点上,为降低复杂度,我们找到子节点最多的节点,把所有同深度的子树放到这个节点上。
对于每一棵树,我们给所有节点设定同一个颜色即可。
1 |
|
Finished…
又开天坑.mp4
做一下SPOJ的8道数据结构,但是什么时候能写完我也不知道qwq
这个很多帖子都有讲,主要就是google的recaptcha用不了,把它更换成recaptcha.net
的验证(虽然尝试跨越长城了,但是仍然用不了,不知道为啥)
解决方法就是安装 Gooreplacer(for Microsoft Edge)
下载完成后,点击橙色小刷子,在弹出的窗口中点击最上方的蓝色按钮“配置规则”。点击页面中表格上方的“新增”,在弹出的窗口内依次输入 www.google.com/recaptcha
,“通配符”,recaptcha.net/recaptcha
,点击“提交”。
这个比较简单,就是最基本的一个框架。
一个节点有4个部分:区间和sum、区间最大前缀和lmx,区间最大后缀和rmx,区间最大子段和mx
在算一个区间最大子段和时,会出现两种情况:
在算一个区间的最大前缀/后缀和时,也会出现两种情况:(以前缀和为例)
至此,我们就可以将线段树build起来了,有一个技巧注意一下,因为在接下来的题里也会用:
重定义node结构体的”+“,或者写一个merge函数,表示node之间的加法,因为不仅有pushup会用到,query也会用。
然后关于query没有什么好讲的吧。就这样,看代码。
1 |
|
没写,这个难,咕
1 |
本题在第一题的基础上加入了单点修改,没有任何攻击性(确信
update就很正常,把边界的点重新赋值,然后重新往上pushup一下就行了。
1 |
|
这题跟前面3问好像没啥关系,不知道为啥放这,但是总体架构仍然不变。
区间求和没有什么难度,但是在修改的时候如果每一个数用sqrt开一下方,常数会剧增,因此需要讨论一种特殊情况:
如果这一个区间的最大值已经<=1了,那么对其开方不会有用,可以跳过
所以在记区间和的基础上记一个区间最大值即可。
1 |
|
在第三题的基础上加入树链剖分。
1 |
|
然而已经很久没有写题解了,天天模拟赛挂大分(摆=__=)
随机选取幸运题目,然而是dp
首先这道题的“概率”非常扯,因为和求这个概率 $\frac{a}{b}$ 就相当于分别求一下 $a$ ,$b$ 然后相除。
分母非常好算,就是所有掷骰子的方案总和,全部乘起来即可。
分子则需要考虑 万能的 动态规划。因为我们只考虑总点数为10以内的情况,所以所有点数大于10的情况实际上是等价且不会影响结果的,而10很小,因此考虑状压。
用数组 $dp[i][s]$ 表示枚举到第 $i$ 枚骰子,状态为 $s$ 的方案数,其中 $s$ 是一个11位二进制数,分别表示点数和为0~10的情况。分别枚举每一枚骰子掷出的所有点数,进行状态转移,而如果可以掷出大于10的点数,对转移没有影响,单独加起来即可。
1 |
|
好啦,你A了一道蓝题喵。时间复杂度 $O(100Sn)$ 其中 $S=2^{11}$ 。
题解:洛谷P1149 [NOIP2008 提高组] 火柴棒等式 加强版!!!
洛谷の原版,原题n<=24,暴力即可,本题n<=30000。
内存限制:128 MiB
时间限制:3000 ms
给你n根火柴棍,你可以拼出多少个形如“A+B=C”的等式?等式中的A、B、C是用火柴棍拼出的整数(若该数非零,则最高位不能是0)。用火柴棍拼数字0-9的拼法如图所示:
注意:
- 加号与等号各自需要两根火柴棍
- 如果A≠B,则A+B=C与B+A=C视为不同的等式(A、B、C>=0)
- n根火柴棍必须全部用上
答案对 1000000007 取模输出
n <= 30000
为了达成复杂度 $O(可过)$,考虑类似数位dp的写法,对A和B按位考虑,再求得C,总体分为以下几个部分:
即可写出数位dp的dfs框架:(是否为最低位,A结束,B结束,进位,剩余火柴)
1 | int dfs: bool zero, bool enda, bool endb, bool carry, int sum: |
非常的简单,直接代码
1 |
|
找不到其他可以测的地方,两个样例:
样例输入1
1 | 30000 |
样例输出1
1 | 75143404 |
样例输入2
1 | 20000 |
样例输出2
1 | 990516656 |
题解:洛谷P2929 [USACO09HOL] Transmission Delay G
给出 $N (1 \leq N \leq 2000)$ 表示 $01$ 串的长度, $D(O \leq D < N)$ 表示 $0$ 或 $1$ 的最大偏离距离,一个长度为 $N$ 的 $01$ 串和一个整数 $K(1 \leq K \leq10^8)$,请计算传输延迟发生后一共有多少种可能的 $01$ 串,以及其中第 $K$ 大的串是什么。
首先这是一个分成两问的 DP 问题。通过原题,$01$ 串中两种位各自的数量不会发生变化,所以对于 DP 的状态,我们可以选用 $0$(或 $1$ )的数量,即:$f[i][j]$ 表示 $i…n$ 为中使用 $j$ 个 $0$ 的方案数,这里倒着处理是为了求第二问。
另外,已知 $K(1 \leq K \leq10^8)$ ,如果 $f$ 数组的某一位超过 $10^8$ 那么它就会被取模,这会导致错误,因此我们开一个 $g$ 和 $f$ 的操作基本一致,但是如果某一位超过 $10^8$ ,就直接将其改为 $10^8+1$。
具体的转移还是比较直接的。
1 |
|
其实下面的这个题是一个简化版本,原题要给dp数组开滚动数组,这个很简单就不写了;还有就是原题要输出方案,注释在代码里。
Luogu: [APIO2014] 序列分割
小H最近迷上了一个分隔序列的游戏。在这个游戏里,小H需要将一个长度为n的非负整数序列分割成k+1个非空的子序列。为了得到k+1个子序列,小H需要重复k次以下的步骤:
1.小H首先选择一个长度超过1的序列(一开始小H只有一个长度为n的序列——也就是一开始得到的整个序列);
2.选择一个位置,并通过这个位置将这个序列分割成连续的两个非空的新序列。
每次进行上述步骤之后,小H将会得到一定的分数。这个分数为两个新序列中元素和的乘积。小H希望选择一种最佳的分割方式,使得k轮之后,小H的总得分最大。
输入第一行包含两个整数n,k(k+1≤n)。
第二行包含n个非负整数a1,a2,…,an(0≤ai≤10^4),表示一开始小H得到的序列。
输出第一行包含一个整数,为小H可以得到的最大分数。
1 | 7 3 |
1 | 108 |
数据满足2≤n≤100000,1≤k≤min(n -1,200)。
注意,输入的a[i]里可能有0
$f[l][r][k]$: 将[l,r]这个区间,切k刀,所能得到的最大得分
$f[l][r][k]: \max_{i=1…n-1, j=0..k-1}f[l][i][j]+f[i+1][r][k-1-j]+(sum[r]-sum[i])*(sum[i]-sum[l-1])$
p.s. 当我们确定了最后切分出来的是哪些区间,我们的答案就是一样的
时间复杂度 $O(n^4)$
使用前缀和优化:
$f[m][i]$: 前 $a[1]..a[i]$ 分成m段,这前m段所贡献的最大得分和
记 $s[i]=\sum_{k=1..i}a[k]$
$f[m][i]=\max_{j=0..i-1} f[m-1][j]+(s[i]-s[j])*s[j]$
$s[i]$: 前缀和
$f[m][i]=\max_{j=0..i-1} f[m-1][j]+(s[i]-s[j])*s[j]$
从小到大枚举m,固定当前m,考虑到当前在计算f[m][i]:
假如有两个不同决策点j,k,尝试分析它们谁更优:
不妨设 j<k<i
对于当前的i,k比j更优等价于:
将j,k分到不等式一侧,i分到另一侧得:
$s[i]>(f[m-1][j]-f[m-1][k]-s[j]^2+s[k]^2)/(s[k]-s[j])$
记右式为 $g(j,k)$,左式为 $h(i)$
对于固定的m,有j
三个决策点,易知,有 j1
双端队列维护j[l]…j[r]从小到大,g函数也是从小到大的
对于任意 $l+1<=x<=r-1$ 有:$g(j[x-1],j[x])<g(j[x],j[x+1])$
1 | //框架 |
然后我们可以解决本题
1 |
|
$f[m][i]=\max_{j=0..i-1}f[m-1][j]+(s[i]-s[j])*s[j]$
=$f[m-1][j]-s[j]s[j]+s[j]s[i]$
$A(j)=f[m-1][j]-s[j]*s[j]$
$B(j)=s[j]$
$C(i)=s[i]$
相当于我们有若干个选项 j,每个j提供一个一次函数 y[j]
$y[j]=A(j)+B(j)*x$
对于所有 $y[0]..y[i-1]$,找一个最大的作为 $f[m][i]$ 的答案
此时我们维护若干个一次函数,要支持插入和求最大值
对于本题的特殊的单调性,即每次插入的 $B(j)$, $C(i)$ (斜率和横坐标)都是递增的
于是,我们可以用双端队列来维护
1 | //框架 |
与刚刚的单调队列优化相比,$g(j1,j2)$ => 交点x坐标 $h(i)$ => $C(i)$
此处也可以用维护凸壳来实现
一般地,给定dp方程
$f[i]=\max_{j=1..i-1} W(i,j)$
通过恒等变形,使其变成:
$W(i,j)=\frac{A(i)-B(j)}{C(i)-D(j)}$
这使得我们联想到了斜率公式
$k=\frac{Δy}{Δx}=\frac{y2-y1}{x2-x1}$
这样可以询问到一个点连到现有的点的斜率最大
如何维护下凸线?
如果每次加入点的x坐标是单调增的:和上面两种方法几乎一样的单调队列写法即可维护下凸线
如何处理查询?
对于给定的查询点,凸壳上的点到这个查询点的斜率是先严格单调增,(然后可能会恒等不变一段),然后再严格单调减的。
在凸壳上使用三分法
斜率优化代码会长成这样:(其实长得跟上面的没什么区别qwq)
1 | double slope(int a,int b) |
考虑一个dp方程 $dp[i]=\max_{j=1..i-1} W(i,j)$
对于某两个 $j1<j2$,如果在某个 $i$ 处 $j2$ 比 $j1$ 优,那么在更大的 $i$ 处 $j2$ 也一定比 $j1$ 优。
即满足强决策单调性:一旦一个后来者超过你,他就会一直超过你,所以随着i增大,最优决策点也严格单调增
而本题满足 $h(i) > g(j1, j2)$ ,可以使用二分队列的方法进行优化
考虑:每个决策点j,是哪些i的最优决策点
对于每个 $j$,它成为最优决策点的 $i$ 要么不存在,要么一定是一段连续的区间,记为 $[l_j,r_j ]$
对于 $ j1<j2$,且 $[l{j1},r{j1} ]$ 和 $[l{j2},r{j2} ]$ 都不为空,那么有 $r{j1}<l{j2}$
所有这些 $ [l_j,r_j ] $ 构成了 $[1, n]$ 的一个划分
我们尝试维护当前[0,i-1]间的最优决策区间:
但是那些>=i的决策点,未来可能“抢走”当前某个j的 $[l_j,r_j]$ 的一部分,因此当前某个j的 $[l_j,r_j]$ ,只有可能变小,不可能再变大。计算i的最优决策点后,因为只需要计算i往后的,所以我们只需要保留构成[i,n]的划分的那些$[l_j,r_j]$
也就是我们将维护若干个三元组(j,l,r)
然后在队列里二分就可以找到切分点了
最近在学欧拉函数,数学太烂,遂写一题解。
其实这个东西是我5月底咕咕写的,但是1整月了我还没发过东西,所以我今天来把这道题补完
不会欧拉函数
好的,欧拉函数,AKA. Euler’s totient function,AKA. $\varphi(n)$ ,表示小于等于 $n$ 和 $n$ 互质的数的个数
这个 $\varphi(n)$ 是满足积性函数的性质的:
$\gcd(a,b)==1 \rightarrow \varphi(ab)=\varphi(a)\varphi(b)$
还有一些性质:
$n=\sum_{d|n} \varphi(d)$
$n=p^k \rightarrow \varphi(n)=p^k-p^{k-1}$
$n=\prod{i=1}^{s}p_i^{k_i} \rightarrow \varphi(n)=n\times\prod{i=1}^{s}\frac{p_i-1}{p_i}$
…
重点,是如何快速求出欧拉函数
现在我们处理好数组 $p[]$,表示一个范围内的质数(可以用欧拉筛)
若对于 $i$,如果已知所有的 $1−i$ 的 $\varphi $,枚举 $<=i$的质数 $p[j]$,可以求得 $\varphi (x×p[j])$
1.若 $p[j]$ 与 $x$ 互质 $\varphi (x \times p[j])=\varphi (x)\times\varphi (p[j])$
2.若不互质,设 $x=t\times p[j]^k$
$\varphi (x \times p[j])=\varphi (t \times p[j]^{k+1})=\varphi (t) \times \varphi (p[j]^{k+1})=\varphi (t) \times \varphi (p[j]^k) \times p[j]=\varphi (x) \times p[j]$
1 | ll tot; |
根据题意知道:$\gcd(x,y)=p$为一个素数,因此:$\gcd(x/p,y/p)=1$,即 $x/p,y/p$ 是互质的,因此我们想到欧拉函数。
在原来板子的基础上进行一个前缀和的添加。
正常来说我们会进行一个双层枚举,枚举 $i,j$ 使得 $\gcd(i,j)=1$ 的情况,就相当于分别考虑 $i,j$ 的欧拉函数,对于 $i==j$ 的情况要减一。
1 |
|
Abalabakabala…
博弈论的代码是这样的,别的算法只要考虑码力和思维,而博弈论要考虑的就多了
n堆石子,每堆数量不超过m
当n<=m,n为偶数先手赢,否则后手
当n>m,与上述同理,所以两方都希望最终合并次数变成奇数/偶数,假如现在轮到先手操作,先手还没动,这个时候最长合并次数为偶数次,那么先手有两种可能性,把后面一个堆丢进大堆里面,这样后手再丢一个小堆进去,或者把后面两个堆合成一个,无论怎么做,后手都能保证每轮完了之后,大堆的石子会增加两个,那么合并次数也会-2,一直保持为偶数,而这种方式使得合并次数最多。
那么先手一定会把小堆合并到一个大堆里,直到这一堆变成m个,所以最后的结果就会变成若干堆m个石子和一堆n%m个石子,总共要合并 $(n/m)*(m-1)+(n\%m?(n\%m-1):0)$ 次,再判断是否为偶数
1 |
|
Very good Game Theory…
题解:洛谷P1337 [JSOI2004] 平衡点 / 吊打XXX
玄学算法,但是有必要知道一下以便日后骗分()
太幽默了。
Simulated annealing - Wikipedia
首先这个算法名字就很魔性,还要根据什么固体退火原理,听不懂(bu
其次我们发现这是一个叫做玄学的东西,它的精度会对它的结果和时间复杂度有所影响
使用模拟退火,因为我觉得这就是模拟退火模板题。
1 |
|
看到 JSOI2004]平衡点 / 吊打XXX - 洛谷专栏 (luogu.com.cn) 这个题解用的是二分,先放在这里吧,回头搞一下咩~
这是一道紫题!
我们需要接触一个叫做生成函数的登西。
对于至少 $a$ 个,不超过 $b$ 个的限制,可以先求出限制不超过 $b$ 个的方案数,然后减去限制不超过 $a-1$ 个的方案数,即为答案。
对第 $i$ 个糖果罐列出其的生成函数,得:
因此,设答案为G(x):
1 |
|
咕了,学不懂数学
题解:洛谷P8207 [THUPC2022 初赛] 最小公倍树
巩固一下最小生成树的Kruskal算法()
首先如果我们将完全图的所有边都存下来,最多需要 $(R-L)^2$ 条边,时空复杂度皆到了 $10^{10}$
所以我们选择在存边的部分进行优化
首先对于两个点,它们连边的权值为 $lcm(u,v)$ ,这意味着当 $gcd(u,v)$ 越大,权值越优
因此,对于每一个 $i\in{[1,R]}$,我们枚举它符合在 $[L,R]$ 区间内的倍数存下来
然后套kruskal板子即可
1 |
|
Finished…
题解:洛谷P8074 [COCI2009-2010#7] SVEMIR
虽然这是一道幽默的绿题,但是博主打AtCoder发现自己竟然不会写最小生成树,遂有此文
首先来看一下Kruskal最小生成树算法
将所有的边存下来,并按长度排序
用并查集存储两个点是否在同一棵树上,是则跳过;不是则合并,并将答案加上边长
1 |
|
本题在上边的Kruskal模板上进行一个减边的优化即可
每个星球用三维坐标 $(x_i,y_i,z_i)$ 来表示,而在两个星球 $A,B$ 之间建造隧道的价格为 $\min{|x_A-x_B|,|y_A-y_B|,|z_A-z_B|}$。
所以考虑三个点 $a, b, c$ $(a_x<b_x<c_x) $ 此时连接 $ab$, $bc$ 更优,意思是说,我们会连的边一定是相邻的
1 |
|
题解:洛谷P1041 [NOIP2003 提高组] 传染病控制
感觉我题解越写越水(???
受不了,博主开始写错题题解了。。。
虽然看到了一坨DP和随机化解法但是不如dfs!
你看那小小的 $n$ 小小的(只有 $300$),所以爆搜甚至不用剪枝
感觉思路也不是非常非常非常困难,dfs算一下最多的不被感染人数再用总数减一下即可
1 |
|
发现泄题解还是很水。。。
同余最短路,话说博主图论很烂,所以来做一下
虽然用了被嘲讽的已经死掉的SPFA,但是其实我觉得SPFA没那么好卡
1 |
|
Finished…
由于太弱开始写一些绿题及以上的单题题解
说实话我觉得这身为一道蓝题并不是非常的难qwq
题目明摆着“选择优先级最高的先运行”,于是非常一眼的优先队列
直接蠢蠢地模拟即可
(STL模拟水题真好玩(?
1 |
|
就没了。
蓝题欸。。。
题解:洛谷P4424 [HNOI/AHOI2018] 寻宝游戏
洛谷首黑(虽然很水,并且小小地借助了题解),所以写一下题解作为巩固
非常容易注意到,对于位运算:
所以若要使最终某一位为 $0$,最后一个 $and$ $0$ 要出现在 $or$ $1$ 后面;为 $1$ 同理
后面这个转化借助了一下 StudyingFather 大神的题解思路:
我们设操作序列中 $or=0$ ,$and=1$ ;数字序列从下往上看得到的数为 $x$ ,操作序列从下往上看得到的数为 $y$
这样就将条件转化成:运算最后结果为 $0$ ,当且仅当 $x≤y$ ;为 $1$ 同理
遂将题目转化成求一个不等式组(把结果每一位拆开)
1 |
|
题解:CF1926E Vlad and an Odd Ordering
多么美丽的一道找规律啊!
ps:鄙人太烂了,所以只能写这种入门题的题解。
这道题面非常诈骗,因为只有在奇数的 $2$ 的幂倍时才会有牌被铺开,简易证明如下(十分简单会的可以跳过):
设 $k=2^n×(2m+1)$ ,因此 $x=k×(2y +1)$,其中 $n,m,y∈ \mathbb {N}$ 。
当且仅当 $m=0$ 时,$k=2^n$,否则 $k>2^n$ 且 $k$ 不为2的幂。
所以
又因为当$m≠0$时,$k>2^n$,所以$x$一定已经被铺开过了,该次操作无效。
所以当且仅当在奇数的 $2$ 的幂倍时才会有牌被铺开。
我们不妨来模拟一下:
设共有7张牌:$[1,2,3,4,5,6,7]$
第一次铺开奇数(即 $2^0×$ 奇数)得到 $[1,3,5,7]$,剩下$[2,4,6]$ ;
第二次铺开 $2^1×$ 奇数 得到 $[2,6]$,剩下$[4]$ ;
第三次铺开 $2^2×$ 奇数 得到 $[4]$,没有剩下。
显而易见,第$n$次会铺开$2^{(n-1)}+2^n×m$,其中 $m∈ \mathbb {N}$,$m+1$表示铺开的是这轮操作里的第$m+1$张牌。
而每一次都会铺开剩余牌数的一半向上取整张牌。
因此就搓出了一个短小的解法。
1 |
|
Update your browser to view this website correctly.&npsb;Update my browser now