AtCoder Beginner Contest 212
E - Safety Journey
题意
给出一个含有 N(N⩽5000) 个顶点的完全图,编号从1到N,从中删去 M(M⩽5000) 条边,要求每次从1号顶点出发,经过 K(K⩽5000) 个顶点后,再次返回到1号顶点,求一共有多少种方案数(结果对 998244353 取模)
思路
最一开始在想通过邻接矩阵的取 K 次幂直接计算答案,但是发现不好优化矩阵乘法
发现这类计数问题可以使用dp解决,记一次路径通过的点分别为 A0,A1,…,AK(A0=AK=1)
令 f(i,j) 为走 i 步最后到达的城市为 j 的总方案数,也就是 Ai=j
则转移方程有:
f(i+1,j)=k∈Sj∑f(i,k)
其中,Sj 为顶点 j 所能到达的其他顶点集合
但是这样的转移的复杂度为 O(N),总复杂度为 O(N2K),没有用到 M 的范围
可以通过求一个补集来用到 M
令 Sjˉ 为顶点 j 不能到达的顶点集合
于是转移方程又可以写做:
f(i+1,j)=1⩽k⩽n∑f(i,k)−k∈Sjˉ∑f(i,k)
这样每次转移第二维的复杂度为 O(N+2M),则总复杂度为 O(N2+2MN),就可以过了
初始化:f(0,i)=δi,1={1i=10otherwise
点击显/隐代码
F - Greedy Takahashi
题意
给出N个城市编号从1到N,有M辆巴士,对于每个巴士有四个参数a,b,s,t,分别这辆巴士表示在s+0.5时刻从a城市出发,在t+0.5时刻到达b城市
有一个旅行家,每次都会选择当前时间最近的巴士上车,前往下一个城市,如此往复,直到没有没有巴士可以乘坐,输入保证每个巴士的s值都不相同,就说明他每次的选择都是唯一的
现在有Q次询问,每次询问给出x,y,z,表示在x时刻该旅行家在y城市,求在z时刻时,旅行家所处的位置,如果他正好在某个巴士上,输出巴士对应的城市a和b,否则输出他正处于的城市编号
N,M,Q⩽105
思路
由于旅行家的这种选择巴士的方法,导致他每次选择具有唯一性,就说明两两巴士之间的关系一定是唯一的
乘坐了A巴士那么如果有下一辆巴士B,那么B一定是唯一的
可以视为A和B之间连接了一条有向边
那么每一个巴士都有且只有一个后继
则这些巴士这就构成了一棵树
题目要求最后停止的时间,可以通过树上倍增完成,需要注意在细节上的判断
时间复杂度 O(QlogN)
点击显/隐代码
G - Power Pair
题意
给出一个素数 p,求有多少对二元有序对 (x,y) 满足下列条件:
- 0⩽x,y⩽p−1
- ∃n∈Z⩾1 使得 xn≡y(modp)
答案对 998244353 取模。
思路
当 x=0 时,y=0,反之亦然,则一定存在有序对 (0,0),下面考虑 1⩽x,y⩽p−1 的情况
由于这个题和次幂有关,所以我们考虑取 p 的一个原根 g。
由于 g1,g2,…,gp−1 遍历模 p 的完全剩余系,则只用考虑 (gk)n 在模 p 下的数的个数。
不难发现,这个个数就是它的阶:δp(gk)
又由阶的性质命题5得:
δp(gk)=gcd(δp(g),k)δp(g)=gcd(φ(p),k)φ(p)=gcd(p−1,k)p−1
于是题目变为,求解
1⩽k⩽p−1∑gcd(p−1,k)p−1
但这样直接求解会是 O(P) 的复杂度会超时,但将 p−1 的因数提出来,然后转换为计数问题就能求解了,也就是:
原式=a∣(p−1)∑ap−1f(a)
其中 f(a)=gcd(p−1,k)=a∑1=gcd(ap−1,ak)=1∑1=φ(ap−1),也就是和 p−1 的最大公因数为 a 的数的个数。
由于 a 的取值一共只有 p−1 因数的个数那么多,记 p−1 的因数个数为 d,用容斥的思想求解 f(a),可以通过从大到小计算 f(a),每次计算的复杂度为 O(d),如:
p−1=100,f(10)=100/10−f(20)−f(50)−f(100)
也就是
f(a)=ap−1−a∣b, b∣(p−1)∑f(b)
复杂度为 O(d2)
则总复杂度为 O(P+d2)
点击显/隐代码