井下矿工
Description
有一座地下的稀有金属矿有 $n$ 条隧道和一些连接点组成,其中每条隧道连接两个连接点。任意两个连接点之间最多只有一条隧道。为了降低矿工的危险,你的任务是在一些连接点处安装太平井和相应的逃生装置,使得不管哪个连接点倒塌,不在此连接点的所有矿工都能到达太平井逃生(假定除了倒塌的连接点不能通行外,其他隧道和连接点完好无损)。为了节约成本,你应当在尽量少的连接点安装太平井。还需要计算出当太平井的数目最小时安装方案总数。
Input
输入包含多组数据。每组数据第一行为隧道的条数 $n$; 以下 $n$ 行每行两个整数,即一条隧道两端的连接点编号(所有连接点从 $1$ 开始编号)。每组数据的所有连接点保证连通。 输入数据最后一行包含一个单独的整数 $0$ 表示结束。
Output
对于每组数据,输出两个整数,即最少需要安装的太平井数目以及对应的方案总数。方案保证在64位带符号整数的范围内。
Sample Input Sample Output 9 1 3 4 1 3 5 1 2 2 6 1 5 6 3 1 6 3 2 6 1 2 1 3 2 4 2 5 3 6 3 7 0 Case 1: 2 4 Case 2: 4 1Hint
$100\%$ 的数据: $n\le 50000$
这题输出就很唐。
漂亮数
题目描述
Smart 认为一个数能被它自己的每一位非零数字都整除的数是漂亮数。现在给你两个整> 数 $L, R$,输出区间 $[L, R]$ 中漂亮数的个数。
例如:若 $n=128$,需检查数字 $1,2,8$(非零位)是否都整除 $128$,若都整除则 $128$ 为漂亮数。
输入格式
第一行一个整数 $T$,表示测试数据组数。接下来 $T$ 行,每行包含两个整数 $L_i, R_i$,表示查询区间 $[L_i, R_i]$。
约束:$1 \le T \le 10,\quad 1 \le L_i, R_i \le 9\times 10^{18}$
(20% 的数据:$1 \le L_i, R_i \le 10^5$)输出格式
输出 $T$ 行,每行一个整数,表示对应区间内漂亮数的个数。
样例
Sample Input Sample Output 1 1 9 9 1 12 15 2
这题是数位 DP。
考虑最朴素的做法:
设置状态 $ f \begin{bmatrix} d & \begin{matrix} x_1 \\ x_2 \\ x_3 \\ x_4 \\ x_5 \\ x_6 \\ x_7 \\ x_8 \\ x_9 \end{matrix} & \begin{matrix} s_1 \\ s_2 \\ s_3 \\ s_4 \\ s_5 \\ s_6 \\ s_7 \\ s_8 \\ s_9 \end{matrix} & eq \end{bmatrix} $ 表示从左往右处理到了第 $d$ 位,
现在数字和原来 $ \begin{cases} eq=1: 相等 \\ eq=0: 不相等 \end{cases} $ ,
(从左往右)前 $i$ 位数 $\bmod m$ 的值是 $x_m$,前 $i$ 位数中 $\begin{cases} s_n=0: 不含 n \\ s_n=1: 含 n \end{cases}$ ,
此时所有合法数字的个数。
转移:
$$
\begin{array}{l}
\textbf{For } d = 1 \dots d_{\max} &\small{d: 当前枚举从前往后位数(从小到大)} \\
\quad \textbf{For } \forall i \in \{0 \dots 9\} &\small{i: 当前枚举数位} \\
\qquad \textbf{For } \forall j=\{x_1 \dots x_9\} &\small{j: 当前枚举模数状态} \\
\qquad\quad \textbf{For } \forall k=\{s_1 \dots s_9\} &\small{k: 当前枚举数字存在状态} \\
\qquad\qquad \begin{cases}
i < n_d: \quad \textbf{Let } f[i, x(j), s(k), 0] \operatorname{ Plus } f[i-1, j, k, 0] + f[i-1, j, k, 1] \\\\
i = n_d: \quad \begin{matrix} \textbf{Let } f[i, x(j), s(k), 0] \operatorname{ Plus } f[i-1][j][k][0] \\ \textbf{Let } f[i,x(j), s(k), 1] \operatorname{Plus} f[i-1][j][k][1] \end{matrix} \\\\
i > n_d: \quad \textbf{Let } f[i, x(j), s(k), 0] \operatorname{ Plus } f[i-1][j][k][0]
\end{cases} &\small{x(j): j 在末尾加上一位 i 后的状态 \\ s(j): 同理 \\ n_d: 原数字中从左往右数的第d位数}
\end{array}
$$
显然这种做法存都存不下,更别提这惊人的时间复杂度了。令总位数为 $n$,时间 $\mathcal O(T \cdot n \cdot 9! \cdot 2^9 \cdot 10 \cdot 2)$,空间 $\mathcal O(9! \cdot 2^9 \cdot 10 \cdot 2)$(在使用滚动数组的情况下)。
容易想到优化:对于 $ x_1, x_2, \dots, x_n $ 一个一个存储记录显然有些浪费,如果记录这个数字 $\bmod \operatorname{lcm}(1,2,\dots,9)$ 效果是一样的。
于是得到了状态 $ f\,[d, x, s, eq] $,时间是 $\mathcal O(T \cdot n \cdot 2520 \cdot 2^9 \cdot 10) $。
Code (20pts)
1 |
|
为什么拿不到满分呢???
实际上,一部分原因是 OJ 太慢了。。。
但是!注意到!
我刚刚推的 DP 实际上是重复算了大量子问题:那就是 $eq=0$ 的情况!
对于这个子问题单独处理为一个 $g$,然后每次 dfs 式地去算答案,这题就能获得正解。
Code (std)
1 |
|
迷宫(动态围墙)
题面描述
Zdrcl 不慎进入了一个迷宫。这个迷宫是一个空的 $N\times M$ 网格,之后会发生 $Q$ 件事件,事件类型如下:
1 x1 y1 x2 y2:在由格子 $(x_1,y_1)$ 到 $(x_2,y_2)$ 所构成的矩形外围出现一堵围墙(围墙沿格边,与格子边重合)。2 x1 y1 x2 y2:上述那堵围墙消失(保证该围墙之前确实出现过)。3 x1 y1 x2 y2:询问 Zdrcl 是否能从 $(x_1,y_1)$ 走到 $(x_2,y_2)$(不能翻越围墙,只能沿网格的四个方向移动)。题目保证:任意两堵围墙之间不相交、没有公共边也没有公共点(即围墙互相独立)。
输入格式
第一行:三个正整数 $N, M, Q$。
接下来有 $Q$ 行,每行五个整数:t x1 y1 x2 y2,表示一条事件。
其中对于添加/删除围墙的事件(即t=1或t=2),保证
$
2 \le x_1 \le x_2 \le N-1,\qquad 2 \le y_1 \le y_2 \le M-1.
$输出格式
对于每个
t=3的查询,输出一行:能到则输出Yes,否则输出No。约束
$
N, M \le 2500, Q \le 10^5.
$样例
Sample Input Sample Output 5 6 5 1 2 2 4 5 1 3 3 3 3 3 4 4 1 1 2 2 2 4 5 3 1 1 4 4 No Yes
显然呢这题我们立刻可以想到 矩阵区间加 和 差分思想。
想要解决这道题目,我们要先明白:使用 Hash 算法根本目的都是为了使用有限的数字去衡量一个较大的数据块,并且做到尽量唯一。
对于本题而言,我们需要一种 Hash 可以快速处理加入和删除。
我想到了使用 unsigned long long 自然溢出,并且对每一次“矩阵加”都赋上一个随机权值,区间加上这个权值,删除时直接减去这个权值。
std 使用的是亦或处理加入删除,但是我觉得比加减还容易被卡,但是这题数据也不强,所以就随便玩玩。
需要用到二维树状数组!这是一个非常简单的数据结构,但是想起来应用确实不容易啊。
Code
1 |
|
平衡字符串
Description
尼克对研究字符串非常着迷。他喜欢翻转它们、排序它们,或者将一个字符串的字母重新排列。一次他写下了一个仅包含字母 a、b、c 的字符串 $S$(长度为 $N$),并可以对该字符串重复执行下面两类操作中的任意一个:
- 选择两个相邻字母,将第二个替换第一个(例如将 “ab” 变为 “bb”)。
- 选择两个相邻字母,将第一个替换第二个(例如将 “ab” 变为 “aa”)。
例如,从 “abc” 可以得到的字符串包括 “bbc”、“abb”、“acc” 等。
记字母 $x$ 在字符串中的频率为 $|x|$(即出现次数)。当对字符串应用上述操作后,若字符串中任意两种字母的频率差不超过 $1$,则称该字符串为平衡串。也就是说要求同时满足
$-1 \le |a|-|b| \le 1$,$-1 \le |a|-|c| \le 1$,$-1 \le |b|-|c| \le 1$。给定初始字符串 $S$,请计算能够通过对 $S$ 进行一次或多次上述操作得到的不同平衡串的数量(若初始字符串已平衡,也应计入)。结果对 $51123987$ 取模后输出。
输入
第一行是整数 $N$,表示字符串 $S$ 的长度。
第二行是字符串 $S$,仅包含字符 a、b、c。注意初始字符串也可能已经是平衡串并应被计入。
输出
输出一行:不同的可达平衡串的数量对 $51123987$ 取模的结果。
样例
样例组 Sample Input Sample Output #1 4 abca 7#2 4 abbc 3#3 2 ab 1样例说明:样例 #1 中合法的字符串有 7 个:“abca”、“aabc”、“abbc”、“abcc”、“bbca”、“bcca”、“bcaa”。
约束与提示
- $45\%$ 的数据: $N \le 100$;
- $100\%$ 的数据: $N \le 150$。
- 模数:$51123987$。