Code+第二次月赛div1题解(转)

T1

####算法一

暴力枚举所有可能的$a_2$并递推判断。复杂度$O(r \times k)$,预期得分10分。

####算法二

$a_k$可以表示为$a_1$与$a_2$的线性组合。使用递推计算出系数,并暴力枚举所有可能的$a_2$判断。复杂度$O(r+k)$,预期得分30分。

####算法三

暴力枚举所有可能的$a_2$并使用矩阵乘法判断。复杂度$O(r \times \log(k))$,预期得分50分。

####算法四

与算法二类似,使用递推计算出系数,此时可以发现可能的$a_2$满足一个同余方程,使用扩展欧几里得或逆元求解即可。可以通过测试点6,7。

####算法五

将算法四中计算系数的方式改为矩阵乘法,可以通过测试点8。

####算法六

由于$p$可能不是质数,所以需要判断不互质的情况,然后使用扩展欧几里得或欧拉定理求解同余方程。可以通过所有数据。

T2

## 算法一(针对测试点1)

我们可以暴力地维护锅所有锅内的食物,并暴力查询即可。

时间复杂度:$O\left( \left( n+Q\right)Q\right)$或$O\left( \left( n+Q\right)Q\log{n}\right)$

期望得分:8分

## 一些想法

我们可以分别维护锅内(未熟)的食物和锅外(已熟)的食物。对于操作$1,3$和操作$2$的第一部分(判定是否有已熟的食物),我们可以在锅外查询;对于操作$2$的第二部分(求最近的熟食),我们可以在锅内查询。

## 算法二(针对测试点1-3)

对于锅内的每种食物,我们分别使用链表(或vector)维护,这样操作$2$查询和操作$0$插入的操作**总**复杂度是$O\left( Q\right)$。

对于锅内食物熟了的时间,我们发现对于每种食物,食物煮熟的顺序和食物被放入的顺序是相同的,于是我们每次事件前暴力维护每个链表即可。总复杂度为$O\left( nQ\right)$。

对于锅外的食物,我们用数组(即$n$个变量)维护。于是对于每种操作$2$的第二部分查询,我们可以用$O\left( 1\right)$的时间回答;对于操作$1,3$的查询,我们可以用$O\left( n\right)$的时间回答。

于是我们即可在$O\left( nQ\right)$的时间复杂度内完成此题。

期望得分:20分

## 算法三(针对测试点4-5)

我们发现每个食物的$s$值均为$1$,也就是说在其被放入锅内后一个时刻即会被煮熟。而题目保证每一时刻最多只有一个事件,因此我们可以认为锅内没有食物。

于是我们只需要用树状数组维护锅外的食物,并支持树状数组上二分,即可轻松解决此题。(当然,我们也可以借助set,不过这可能会使你的程序有更大的常数)

时间复杂度:$O\left( Q\log{n}\right)$

期望得分:16分

## 算法四(针对测试点4-7)

对于锅内,我们可以使用链表(或vector)维护;对于锅外,我们可以用树状数组维护。

由于所有食物$s$值相同,所以所有食物被煮熟的顺序与它们被放入锅内的顺序一致,我们可以用指针维护下一个将要被煮熟的食物的位置,即可快速完成“从锅内到锅外”的操作。

时间复杂度:$O\left( Qlog{n}\right)$

期望得分:38分

## 算法五(针对测试点8-9)

我们发现不存在区间求和操作,于是我们同样适用链表(或vector)维护锅内,用multiset或map维护锅外即可。(这两个数据结构完美支持所有查询、修改操作)

对于食物被煮熟的顺序,我们可以额外使用一个priority_queue或堆来维护锅内的食物,其中关键字为食物被煮熟的时间。每次操作前,我们不断弹出堆顶,直到堆顶还未被煮熟为止,并将被弹出的食物加入锅外即可。

我们也可以将所有操作$t 0 id$拆分成$2$个操作:

1. $t$时刻将食物$id$加入锅内。

2. $t+s[id]$时刻将食物$id$从锅内取出,并加入锅外。

并将所有操作重新按时间顺序排序,然后依次执行。

时间复杂度:$O\left( Qlog{n+Q}\right)$

期望得分:14分

## 算法六(针对所有测试点)

结合算法五和支持二分功能的树状数组即是这道题目的标算。

时间复杂度:$O\left( Qlog{n+Q}\right)$

期望得分:100分

## 针对程序常数的说明

对于使用支持二分功能的树状数组、priority_queue以及multiset或map的程序,在实际运行速度上有着一些不同。这是因为前两个数据结构的常数远小于后二者。对于使用其他数据结构的程序,有可能同样会有不同程度的常数问题,选手也因此会得到$96-100$的分数(即有可能无法通过最后两个测试点)。

在实际测试中,上面提到的四种数据结构都可以获得$100$分。

T3

## 短短的题目 给定 $n$ 行 $m$ 列的网格,每个格子中有上下左右四个方向之一的箭头或“`.`”符号(整个网格中共有 $k$ 个)。在每个标有“`.`”的格子中填入一个箭头,使得从任何一个格子出发沿着箭头所指的方向行走,都不会进入循环,求填入的方案数。 ## 长长的题解 ### 一


测试点编号


$n$, $m$


$k$


特殊约定


1


$\leq 50$


$= 0$



2


$\leq 200$

我是来自 Div. 2 的小可爱,已经 AK 啦,所以来看看题,不过好难的样子…… 嗯? 对于 $k = 0$ 的情况,直接按题意进行检查可以通过第 1 个测试点,时间复杂度 $O(n^2 m^2)$;加入记忆化可以通过第 2 个,时间复杂度 $O(nm)$。 ### 二


测试点编号


$n$, $m$


$k$


特殊约定


3


$\leq 2$


$\leq 4$



4


$\leq 4$


$\leq 7$


5


$\leq 10$


6

对于 $k$ 很小的情况,可以直接进行搜索。 枚举每个待确定的格子内填入的箭头方向并检查合法性,时间复杂度 $O(4^k \cdot nm)$。取决于评测环境,第 5、6 个测试点可能需要少量常数优化。 ### 三


测试点编号


$n$, $m$


$k$


特殊约定


11


$\leq 200$


$\leq 200$


$n = 1$


12

只有一行,看着就很像 DP 的样子…… 用 $f[i][s]$ 表示已经确定了左起前 $i$ 个格子的状态,第 $i$ 个格子中箭头方向为 $s$(取 $1$ 至 $4$ 依次表示上下左右)的方案数。按照第 $i$ 个格子是否是“`.`”分开讨论进行转移。 另一个思路是计算**不包含**连续两个格子依次填入“右、左”的方案数——总之怎么做都可以啦。 ### 四


测试点编号


$n$, $m$


$k$


特殊约定


7


$\leq 10$


$\leq 100$



8


9


10

没有环…… 每个格子有一条出边…… [反向树形图](https://en.wikipedia.org/wiki/Arborescence_%28graph_theory%29)(anti-arborescence)? 要选择某些格子的出边…… [生成树形图](https://en.wikipedia.org/wiki/Spanning_tree#In_directed_multigraphs)?! 我们希望建立一张有向图,使得它得生成树形图与填入箭头的方案一一对应。这样一来,该有向图的生成树形图的数量,即为所求的方案数。 事实上,可以通过下列方式建立这张图: * 将每个格子视作一个节点,并增加一个节点对应整个网格的外部区域; * 对于每一个标有箭头的格子,建立一条由**其对应的节点**连向**其中箭头指向的目标所对应节点**的有向边; * 对于每一个标有“`.`”的格子,建立四条由**其对应的节点**分别连向**四个方向邻居所对应节点**的有向边(保留重边——可能出现在网格的角落位置)。 > 例如,对于样例中的第二组数据: > > ``` > ← ← → → > ← . ← ← > → → . → > ← ← → → > ``` > > 建成的图如下所示。 > > ![sol_2](sol_1.png) 容易发现,这张有向图以**网格外部区域所对应节点**为根的反向生成树形图,与填入箭头的方案一一对应。 按上述方式建立有向图,利用有向图的[矩阵树定理](https://en.wikipedia.org/wiki/Kirchhoff%27s_theorem)计算其生成树形图的数目。时间复杂度为 $O((nm)^3)$。 ### 五


测试点编号


$n$, $m$


$k$


特殊约定


13


$\leq 200$


$\leq 200$


有且仅有第 $1$ 行的所有格子中标记未确定


14


15


16


$\leq 300$



17


18


19


20

对于第 13 至 15 个测试点,相当多节点的出边是已经确定的,因此可以通过将不必考虑的点进行收缩,使需要计算的节点数降至可接受的 $O(n)$ 范围,达到 $O(n^3)$ 的时间复杂度,在此不必赘述。其实是王队长说要把这个子任务留着的,你们要知道具体怎么做就去问他吧 对于没有特殊约定的数据亦同理,考虑去除图中不必要的点。 给每个标有“`.`”的格子进行编号,用 (0) 表示网格外围。预处理每个标有“`.`”的格子朝四个方向出发行走时,到达的第一个带有编号的位置。 > 例如,对于样例中的第二组数据: > > ``` > ← ← → → > ← (1) ← ← > → → (2) → > ← ← → → > ``` > > 预处理的结果如下: > > | Source | ← | → | ↑ | ↓ | > |:--:|:--:|:--:|:--:|:--:| > | (1) | (0) | (1) | (0) | (2) | > | (2) | (2) | (0) | (1) | (0) | 将前述的建图方法改变如下: * 将每个标有“`.`”的格子视作一个节点,并增加一个节点对应整个网格的外部区域; * 对于每一个标有“`.`”的格子,建立四条由**其对应的节点**分别连向**四个方向到达的第一个“`.`”格子或网格外围所对应节点**的有向边(保留重边——可能出现在网格的角落位置)。 > 对于样例中的第二组数据,得到的有向图如下: > > ![sol_2](sol_2.png) 这张有向图以**网格外部区域所对应节点**为根的反向生成树形图,仍与填入箭头的方案一一对应。 这种建图方法得到的图的节点数为 $O(k)$,利用矩阵树定理计算生成树形图个数即得答案。时间复杂度 $O(nm + k^3)$。 (另一种殊途同归的思路是直接将已经确定的节点进行收缩,实际得到的图应该是相同的。) ### 六 由于数据范围不大,并不知道是否存在诸如 $O(4^{\sqrt k})$ 或者 $O(4^n)$ 的状压 DP 部分分解法…… 如果对于这份题解有疑问,或者使用了其他奇妙的方式处理本题,也欢迎在群里戳出题人并和大家讨论 :) ## 数据那些事儿 本题数据中的箭头方向主要由四种方式生成:**随机**、**树**、**迷宫**和**同向**。 * **随机**:正如字面意义,随机每个格子的箭头方向。当然这样生成的地图很容易产生环而导致不合法,因此特意避免了相邻两个格子互相指向的情况(然而数据大了还是有很多环 = =)。 * **树**:传入一个参数 `factor`,为 $[0, 1]$ 间的实数。每次取一个网格边界的格子或一个四周有空格的格子,随机行走并沿途标上对应的箭头。每一走步有 `factor` 的概率退出本次循环,当无路可走时也退出本次循环。大部分测试数据由此方法生成。 * **迷宫**:从一个角落开始,每次随机选择一个方向走到底并拐弯。生成的地图大概长这个样子: ``` → → → → → → → → → → ↑ → → → → → → → → ↓ ↑ ↑ ← ← ← ← ← ← ← ↓ ↑ ↓ ← ← → ↓ → ↓ ↑ ↓ ↑ ↓ → ↑ ↑ ↓ ↑ ↓ ↑ ↓ ↑ ↓ ↑ ← ↑ ↓ ↑ ↓ ↑ ↓ ↑ ↓ → ↑ ↑ ↓ ↑ ↓ ↑ ↓ ↑ ↓ ↑ ← ↑ ↓ ↑ ↓ ↑ ↓ ↑ → → → ↑ → ↑ → ↑ ↓ ↑ ← ← ← ← ← ← ← ← ← ``` 这样做的目的是使未记忆化的行走过程达到 $O(n^2 m^2)$ 的上界。而且这样的图超好玩的不是嘛(逃 * **同向**:大部分箭头同向,混入少量随机。不知道有啥用,大概是为了好玩(???) 以上。今天的 Div. 1 第三题,希望大家喜欢 \(?′ω`?\)

时间: 2024-10-08 16:44:40

Code+第二次月赛div1题解(转)的相关文章

csu-2018年11月月赛Round2-div1题解

csu-2018年11月月赛Round2-div1题解 A(2191):Wells的积木游戏 Description Wells有一堆N个积木,标号1~N,每个标号只出现一次 由于Wells是手残党,所以每次只能取出一块积木放在积木顶层 现在Wells想知道至少需要操作几次可以把积木堆成从顶至底标号升序 不论什么都很菜的Wells显然不知道怎么做 所以作为人生赢家的你义不容辞的决定帮助可怜的Wells Input 第一行一个正整数N 接下来N行,从顶至底描述每块积木的标号 Output 输出一行

csu-2018年11月月赛Round2-div2题解

csu-2018年11月月赛Round2-div2题解 A(2193):昆虫繁殖 Description 科学家在热带森林中发现了一种特殊的昆虫,这种昆虫的繁殖能力很强.每对成虫过x个月产y对卵,每对卵要过两个月长成成虫.假设每个成虫不死,第一个月只有一对成虫,且卵长成成虫后的第一个月不产卵(过X个月产卵),问过Z个月以后,共有成虫多少对?0=<X<=20,1<=Y<=20,X=<Z<=50 Input 单组数据 x,y,z的数值 Output 过Z个月以后,共有成虫对

Topcoder SRM 607 div1题解

好久没来写了,继续继续... Easy(250pts): //前方请注意,样例中带有zyz,高能预警... 题目大意:给你一个字符串,中间有一些是未知字符,请你求出这个字符串的回文子串个数的期望值.数据满足字符最多2500个. 我们考虑每一个子串,它对答案的贡献度就是它是回文串的概率,那么我们扫一遍就可以了, 这样做时间复杂度O(n^3),显然过不去. 我们考虑一下对于一个子串,在判断其是回文串的时候,我们一定是从中间往两边扫的,那么其实中间这些子串我们已经统计过答案了, 也就是说,我们通过枚举

Contest1592 - 2018-2019赛季多校联合新生训练赛第二场(部分题解)

D 10248 修建高楼 D 传送门 题干 题目描述 C 市有一条东西走向的"市河".C 市的市长打算在"市河"的其中一条岸边自东往西的 n 个位置(可以将这 n 个位置看成在一条直线上,且位置不会重叠)依次建造高楼. C 市的设计部门设计了 T 个方案供市长挑选(方案编号为 1 到 T).每个方案都提供了建造的每幢高楼的高度,自东向西依次为 h1,h2,h3,-,hn-1,hn.每幢楼房的高度在 1 到 n 之间(包括 1 和 n),且各不相同. 市长在挑选设计方

Topcoder SRM 605 div1 题解

日常打卡- Easy(250pts): 题目大意:你有n种汉堡包(统统吃掉-),每一种汉堡包有一个type值和一个taste值,你现在要吃掉若干个汉堡包,使得它们taste的总和*(不同的type值的个数)乘积越大,输出这个最大值.数据满足n<=50,type<=100,abs(taste)<=100000. 这题好像是个贪心,才不是呢啊哼- 首先我们发现,如果若干个汉堡包有同一个type值,那么我们可以把这一些汉堡包看成一个新的大汉堡包,它的type就是原来的type,它的taste就

洛谷2018寒假集训tg第二次比赛第二题Princess Principal题解

这算不算泄题啊...被kkk发现会咕咕咕吧. 题目大意:给定一个数列a,与常数n,m,k然后有m个询问,每个询问给定l,r.问在a[l]到a[r]中最少分成几段,使每段的和不超过k,如果无解,输出Chtholly 样例: input: 5 5 72 3 2 3 43 34 45 51 52 4 output: 11122 解答: 首先观察数据范围,n<=1e+6 可能的复杂度为O(mlogn).暴力能搞30分吧. 其实这题还是很妙的.我们先考虑暴力:对于[L,R],设个res,对[l,r]从左往

洛咕11月月赛部分题解 By cellur925

听说是你谷史上最水月赛?我不听我最菜 T1:终于结束的起点 月天歌名好评 给你一个模数 \(M\),请你求出最小的 \(n > 0\),使得\(fib(n)\) \(mod\) \(m=0\),\(fib(n+1)\) \(mod\) \(m=1\). 数学题,开始还想打表验证下,但是我不会告诉你我打表的时候没有很及时地取膜,然后中间有结果溢出,耽误了很长时间,企图找了很久规律.结果发现暴力就能过.hhh. 这个故事告诉我们要及时取膜! #include<cstdio> #include

集训队寒假集训第二场补题题解

补题什么的待填坑... A - Generous Kefa (语法基础) 直接开桶看看有没有超过三个的,因为题目明确提出没有气球也是可以的 代码 #include <bits/stdc++.h> using namespace std; int bk[123213]; int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); int n,k; cin>>n>>k; string a; cin>&g

Code Chef January Challenge 2019题解

传送门 \(div2\)那几道题不来做了太水了-- \(DPAIRS\) 一个显然合法的方案:\(A\)最小的和\(B\)所有连,\(A\)剩下的和\(B\)最大的连 算了咕上瘾了,咕咕咕 const int N=2e5+5; int A[N],B[N],id[N],mxb,mxa,n,m; int main(){ // freopen("testdata.in","r",stdin); n=read(),m=read(),A[0]=inf,B[0]=-inf; f