2019年湖南省大学生计算机程序设计竞赛 (HNCPC2019) 简要题解
update10.01 突然发现叉姐把这场的题传到牛客上了,现在大家可以有地方提交了呢。
不知道该干什么所以就来水一篇题解
题解全是根据印象口胡的,代码是不可能重新写的,这辈子不可能重新写的。
A
description
有一个(n imes m)的全(0)矩阵,选择一个子矩阵全部修改成(1),现在给出修改后的矩阵,问是否存在合法修改方案。
(1 le n, m le 10.)
solution
找到最左上的(1)和最右下的(1),判断是否中间全是(1),剩下的全是(0)就好了。
需要特判没有(1)的case。
B
description
给出(n,k),求(min(inom{n}{k},10^{18}))。
(0 le k le n le 10^9.)
solution
gzy写的,他一遍过了,反正gzynb就对了。
先令(kle lfloorfrac n2
floor),然后再(O(k))计算组合数,即每次乘一个数再除一个数,可以用long double
或__int128
判断是否超过(10^{18}),一旦爆了就直接输出(10^{18})。
C
description
给出一个长度为(n)的字符集大小为(m)的串,对于(forall iin[1,m]),求往字符串后面新增一个字符(i)后增加了多少本质不同的子串。
(1 le n,m le 10^6.)
solution
枚举原串的一个后缀,找出这个后缀在串中的其他出现位置,此时可以更新这个位置往后一个字符对应的答案。
实现中可以使用后缀自动机(只要从自动机上原串对应的那个点出发一直跳(fail)就行了)或者exkmp(线性求原串与所有前缀的(lcs))。
D
description
求有多少长度为(n)的序列({a_i})满足:
- (a_i in [0,9].)
- 满足(m)条限制,每条限制给出(l,r),要求(prod_{i=l}^ra_i equiv 0 mod 9.)
方案数对(10^9+7)取模。
(1 le n,m le 50.)
solution
限制即为要求区间内存在至少两个(3)的质因子,在这里可以认为(0)包含(infty)个(3)质因子。
记(dp_{i,j,k})表示前(i)个位置,最近的两个(3)质因子在(j,k)的方案数,转移是先判掉不合法(对每个限制的右端点维护对应最大左端点),然后在考虑第(i+1)位上是填({0,9})还是({3,6})还是({1,2,4,5,7,8})。
E
description
给一个数字串(S),要求将(S)划分成若干互不相同的([0,99])内的整数,不能含有前导零,求方案数。
(1 le |S| le 50.)
solution
直接搜。
考虑一位数(包括(0))只有(10)个,那么确定了一位数的位置后剩下的划分也就随之确定了,假设数字(i)出现了(a_i)次,那么搜索的总状态数不超过(prod_{i=0}^9(a_i+1) le (frac{sum_{i=0}^9(a_i+1)}{10})^{10}=6^{10})。
F
description
一个人初始在((0,0)),可以走不超过(n)步,每一步可以向右走不超过(a)步,或者向上走不超过(b)步,或者向左走不超过(c)步,或者向下走不超过(d)步,求这个人可到达的位置数(mod 10^9+7)。
(1 le n,a,b,c,d le 10^9.)
solution
等差数列求和直接算就好了。
G
description
有一个(n imes m)的矩阵({C_{ij}}),需要构造一个(m)阶排列(sigma),使得矩阵的所有列向量根据(sigma)重新排列后满足行向量字典序单调不降。要求输出满足条件的字典序最小的
(1 le n,m le 2000.)
solution
考虑(n=2),那么每一列的两个数的大小关系只有以下三种:(C_{1j}>C_{2j})或(C_{1j}=C_{2j})或(C_{1j}<C_{2j})。由于需要满足第二行的字典序大于等于第一行,那么所有(C_{1j}>C_{2j})的(j)都需要排在至少一个(C_{1k}<C_{2k})的(k)后面。
这个限制可以抽象成:给出({1,2,...,m})的两个子集(A,B),满足(Acap B = varnothing),要求在最终的排列(sigma)中,(B)中每个元素都至少排在一个(A)中元素的后面。
(n>2)的情况就是给出了多组(A,B)。
令每个点的入度为包含这个点的(B)集合数量,每次选择一个入度为零且编号最小的点(保证字典序最小)放在当前排列末尾,如果这个元素在某些(A)集合内是第一次出现,那么就把这个(A)对应的(B)中所有元素的入度减(1)。
总时间复杂度(O(nm+mlog m))。
H
description
一张(n+m)个点的图,初始在(1)号点,每次在(i)号点的时候有(P_{i,j})的概率走到(j)号点,保证(forall iin[n+1,n+m],P_{i,j}=[i=j])。可以发现经过无限次行走后停留在前(n)号点上的概率是(0),求停留在后(m)号点每个点的概率(mod 10^9+7)。
(1 le n + m le 500.)
solution
设(f_i)表示经过(i)点的期望次数,于是
高斯消元解出(f_i)后随便算一下就好了。
I
description
给一棵树,边有边权,求有多少条路径满足边权和是(2019)的倍数。
(1 le n le 20000.)
solution
点分即可。
J
description
给出(n)个(m)元组((a_1,a_2,...,a_m)),记(count(x))表示有多少个(m)元组满足(forall jin[1,m],popcount(a_jland x))为奇数。求(sum_{x=0}^{2^k-1}count(x)3^x mod 10^9+7)。
(1 le n le 10^4, 1 le m le 10, 1 le k le 30, 0 le a_i < 2^k.)
solution
对于每个(n)元组单独求答案然后相加即为答案。
把(m)元组写成一个(k imes m)的(01)矩阵,相当于选出一些行向量做异或运算,要求结果为(2^m-1)。直接按二进制位(dp),记(f_{i,j})表示处理完前(i)位,当前二进制状态为(j(jin[0,2^m)))的方案数。
总复杂度是(O(nk2^m)),大概能过的样子。
K
description
维护(n)个链表以及(m)次操作,每次操作为将一个链表剪切到另外一个的后边并将其翻转。
(1 le n,m le 10^5.)
solution
直接启发式合并即可。
不过要我写可能就直接上treap了。