北化排位赛(三)A-N[简中]
BUC3399A 源码星球的春运机场
思路 求 $P+Q,~P+R,~Q+R$ 的最小值.
代码
1 | void eachT() { |
BUC3399B 源码星球的新春日期
思路 如果前 / 后两个数在 $1\sim12$ 之间,就有可能是月份.
代码
1 | void eachT() { |
注意 || 的优先级高于 &&,要加括号.
BUC3399C 源码超人的电子鞭炮
思路 只要 $0$ 和 $1$ 挨着就会爆,那么最后不可能同时存在 $0$ 和 $1$,进而,爆的组数是 $0$ 和 $1$ 个数的较小值.
代码
1 | void eachT() { |
BUC3399D 源码超人的新年家务
「 $ddl$ 是第一生产力.」——源码大学校长
思路 想想上学期的 ddl 是如何安排时间的……一定是卡着 ddl 完成,然后从 ddl 往前推开始完成的时间.我们按照 ddl 按时间倒序,倒着推导每一项任务的开始完成时间,这个时间便是下一项任务的 ddl.
代码
1 | struct node { |
BUC3399E 一兆吉祥话
注意 别直接 copy 样例就输出了,XX 是需要计算的( 你猜为什么 WA:AC=1:1
思路 假定不能百度搜索在线日期计算器,那就只能手算了:
大致推断是在 $1024$ 年之后,我们计算从 $2022.2.11\sim3046.2.10$ 共多少天,只需算闰年有哪些.
从 $2022\sim3046$ 年,$4$ 的倍数有 $\frac{1024}{4}=256$ 个,$100$ 的倍数有 $2100,~2200,~\dots,~3000$ 共 $10$ 个,$400$ 的倍数有 $2$ 个,总计闰年有 $256-10+2=248$ 年.
于是从 $2022.2.11\sim3046.2.10$ 共 $1024\times365+248$ 天,下面我们从 $3046.2.10$ 向前推 $248$ 天,$3046.1.1\sim3046.2.10$ 共 $31+10=41$ 天,$248-41=202=31+30+31+30+31+31+13$,故答案在 $3045$ 年 $6$ 月倒着数 $13$ 天,即 $30-13+1=18$ 号.
代码
1 | void eachT() { |
提示 本题是全角 %,直接 copy 就可以输出,如果要求输出英文半角 %,需改为 printf(" 新年快乐 %%(^_^)%% from 3045-06-08").
BUC3399F 团团圆圆
思路 电脑模拟操作,我们总是操作最大数和最小数:
1 | const int maxN = 1e3; // 1000 次操作足够,事实上因为数据太弱,5 次就够了 |
我试图推导出 $\Theta(1)$ 的方法:
设所给的数是 $a,b,c$,不妨设它们的最大公约数为 $1$.如果 $3\nmid a+b+c$,显然不能完成.然后呢……不会了……
因为用电脑计算出的结果是这样的:
1
2
3
4
5 1 1 7 1 2 6 1 3 5 1 4 4 1 5 9 1 6 8 1 7 7 1 8 9
2 2 5 2 3 4 2 4 9 2 5 8 2 6 7 2 7 9 3 4 8 3 5 7
3 7 8 4 4 7 4 5 6 4 5 9 4 7 7 4 8 9 5 5 8 5 6 7
5 7 9 5 8 8 6 7 8
// 10 以内的不能完成的(已划去显然不能完成的情况)更大的数也是毫无规律:
1
2
3
4
5
6
7
8
9
10 1 1 7 1 1 13 1 1 16 1 1 19 1 1 25 1 1 28 1 1 31 1 1 34
1 1 37 1 1 40 1 1 43 1 1 49 1 1 52 1 1 55 1 1 58 1 1 61
1 1 64 1 1 67 1 1 70 1 1 73 1 1 76 1 1 79 1 1 82 1 1 85
1 1 88 1 1 91 1 1 97 1 1 100 1 1 103 1 1 106 1 1 109 1 1 112
1 1 115 1 1 118 1 1 121 1 1 124 1 1 127 1 1 130 1 1 133 1 1 136
1 1 139 1 1 142 1 1 145 1 1 148 1 1 151 1 1 154 1 1 157 1 1 160
1 1 163 1 1 166 1 1 169 1 1 172 1 1 175 1 1 178 1 1 181 1 1 184
1 1 187 1 1 193 1 1 196 1 1 199 1 1 202 1 1 205 1 1 208 1 1 211
1 1 214 1 1 217 1 1 220 1 1 223 1 1 226 1 1 229 1 1 232 1 1 235
1 1 238 1 1 241 1 1 244 1 1 247 1 1 250 1 1 253 1 1 256 1 1 259
BUC3399G 一帆风顺
思路 假设你自己是个 贪心的大吃货,你每到一个景点就会吃,如果没得吃怎么办?拿食材呗.去哪里拿?贪心的你当然是选择这个景点之前的可以拿最多食材的那个地方拿.模拟这个过程即可.
注意
- 你实在是太饿了,在一个地方拿还不够吃,可能要反复寻找食材,所以是
while而非if; - 你如果全程一直有的吃,也是要拿食材的,别忘了你是个贪心的人,吃不下也要拿;
- 别太贪心,一个景点只能拿一次,所以领取之后要把这个地方的食材清空.
(以上三条是帮同学 debug 时发现的问题 显然这道题如果不贪心不贪吃是做不出来的)
代码
1 | int a[maxN]; |
BUC3399H 日常与奇迹 - UPSOLVE
思路 区间 DP.
注意到,出现的回文串一定由是 $a$ 串的一个连续子串和 $b$ 串的一个连续子串构成的(比如第二个样例
a和aaaabcaa,可以是a和前面的aaaa组合,可以是a和后面的aa组合,但不能是a和aaaaaa组合),所以我们可以 DP 哪些区间组成的回文串最长.
状态:dp[l1][r1][l2][r2] 表示 $a$ 串的区间 $[l_1,r_1]$,和 $b$ 串的区间 $[l_2,r_2]$ 是否 可以组成回文串;
始态:$a$ 串长度为 $0$ 或 $b$ 串长度为 $0$ 的 dp 全部赋值为 1;
末态:所有满足 dp[l1][r1][l2][r2]=1 的 len1+len2 最大值;
状转方程:dp[l1][r1][l2][r2]=a[l1] == a[l1] == a[r1] && dp[l1+1][r1-1][l2][r2] || b[l2] == b[r2] && dp[l1][r1][l2+1][r2-1] || a[l1] == b[r2] && dp[l1+1][r1][l2][r2-1] || b[l2] == a[r1] && dp[l1][r1-1][l2+1][r2]
状转方程的解释
满足以下四种情形之一的,
dp=1:$a$ 串区间内左端点(第 $l_1$ 位)和 $a$ 串区间内右端点(第 $l_2$ 位)相同,而且 $a$ 串区间 $[l_1+1,r_1-1]$ 和 $b$ 串区间 $[l_2,r_2]$ 已经可以构成回文串,即
dp[l1+1][r1-1][l2][r2]=1,那么 $a$ 串区间 $[l_1,r_1]$ 和 $b$ 串区间 $[l_2,r_2]$ 也可以构成回文串,综合起来的判断条件是a[l1] == a[r1] && dp[l1+1][r1-1][l2][r2];$a$ 串区间内左端点(第 $l_1$ 位)和 $b$ 串区间内右端点(第 $r_2$ 位)相同,而且 $a$ 串区间 $[l_1+1,r_1]$ 和 $b$ 串区间 $[l_2,r_2-1]$ 已经可以构成回文串;
$b$ 串区间内左端点和 $b$ 串区间内右端点相同,且其它部分可以构成回文串;
$b$ 串区间内左端点和 $a$ 串区间内右端点相同,且其它部分可以构成回文串;
(如果 $a$ 串区间内左端点和 $b$ 串区间内左端点相同,是不行的,向回文串上加字母只能往两边加,而不能加在同一边)
把上面四种情形放在一个大大的
if里面,然后更新最大值就好咯.
代码
1 | void eachT() { |
BUC3399I 福被千家
思路 熟知
勒讓德定理:在 $n!$ 中素数 $p$ 的指数
$
v_p(n!)=\displaystyle\sum\limits_{k=1}^{p^k\le n}\bigg\lfloor\dfrac{n}{p^k}\bigg \rfloor=\dfrac{n-S_p(n)}{p-1}.
$
其中,$S_p(n)$ 表示 $n$ 在 $p$ 进制下各个位数的和,熟知
$
S_p(n)=\begin{cases}
1, & \text {if} n=1 \
\displaystyle S_p\Big(\frac{n}{p}\Big), & \text {if} p\mid n \
S_p(n-1)+1, & \text {otherwise}.
\end{cases}
$
我们使用它第一个形式,循环求和.
代码
1 | void eachT() { |
注意 全力开 long long,可以测试一下输入 1000000 能不能出结果,如果什么都输不出来很有可能是 long long 的问题.
BUC3399J 鹏程万里
思路 想要间距尽可能小,一定是左边的向右跳,右边的向左跳,但是界限不确定,我们可以枚举界限,一一计算.假设现在的分界点是 $i$,左边向右跳之后的坐标为 $a_1+x\sim a_{i-1}+x$,右边向左跳之后的坐标为 $a_i-x\sim a_n-x$,综合来看,坐标为 $\min(a_1+x,~a_i-x)\sim \max(a_{i-1}+x,~a_n-x)$.
代码
1 | void eachT() { |
BUC3399K 下笔成章
思路 哈希.参见Link.
倒着按照长度循环,判断前缀和后缀是否相同,如果相同,再寻找中间是否有相同的,如果找到就终止循环.
1 | const int H = 131; |
BUC3399L 鸿运连三江
(涉及知识盲区了)(暂无代码,不确定这个思路能否实现)
思路
BUC3399M 鑫源通四海
(此方法复杂度极高,不建议学习)
思路
BUC3399N 赞美太阳
思路 和 K 题类似的哈希.因为和 $A$ 串 $s_0$ 结构相同的字符串构成了一个环,先将 $s_0$ 断环为链,构成一个长度为 $2len_0$ 的串,将所有结构相同的子串的哈希值计算出来,并用 map 标记.对于每个测试样例,从头到尾遍历它的哈希值,并判断这个哈希值是否出现过.
代码
1 | const int H = 131; |


