CSP 模拟20
A:Simple
考场切掉的简单题
但是有些思想挺好的
ax + by = c
如果只考虑 ax = c,by = c
那么显然好数的个数是\(c/a + c/b - c / lcm(a,b)\)
现在考虑ax + by = c
发现可以枚举y 然后去每次求x
ax = c - by
那么此时的个数显然是\((c-by)/a\)
但是直接枚举显然会有重
考虑什么时候会有重复的
假设此时枚举到ax = c - ky
那么前面有一个状态是 a'x = c - k'y
此时就重复了
因为前面已经筛过
举个例子:
14 6 80
首先80/6 = 13
求得的是6的整倍数 这些好数
然后(80-14)/6
可以理解为先垫一个14 然后再筛6的整倍数
显然这些是不重的
而如果(80-42)/6
此时会重,原因是(80-42)/6
其实就是(80-6*7)/6
这个在第一次筛的时候已经筛出过
考虑什么时候会出现这种情况
显然是当80减去的数大于lcm(a,b)的时候就会出现
所以减去的数只用枚举到lcm
这样复杂度也得以保证
因为最多只会枚举1e5个
但是少算了不放a 只放b的
最后加上就好了
注意不要加重
B:Walk
直接跑显然复杂度是错的
可以枚举gcd 然后只跑gcd为该值的边
即每次建边只建是当前枚举的gcd的整数倍的边
这样就是一个森林
森林中跑树的直径 取最大值就是当前gcd能更新到的最大答案
然后枚举每一个gcd就可以了
为了保证复杂度 不能每次枚举gcd都遍历n个点
所以可以用数组记录边权为gcd的整数倍的点都有哪些
dfs的时候只跑这些点 就可以保证复杂度了
O(\(n^{1.5}\))
C:Weed
和陶陶摘苹果一题类似
线段树维护当前区间的总高度,总层数,以及会向前面的区间删多少层
写一个函数统计向左会删多高就好了
然后直接大力开码就好了
D:Drink
咕咕咕