A
考虑逐位确定答案,答案的位数是 O(k+logn) 的,因此可以将问题转化为 O(k+logn) 次询问形如 x1x2x3⋯xk?⋯? 的数有多少种方案将 ? 替换为 0∼8 使得这个数是 10k−1 的倍数。
一个数是 10k−1 的倍数当且仅当从低往高位,每 k 位划为一段,所有段的和是 10k−1 的倍数。
因为段数很少(设为 l),不妨先枚举这个和,即 [i(10k−1)]i=0l。接下来按照在段中的位置,从低往高数位 dp 即可。
时间复杂度 O(log(n+k))。
B:
两面一定是 1 或出现过的数字,因此可以离散化。
如果不考虑买硬币的代价,两面是独立的,先求出一面是 a 时的收益 Sa,这可以简单通过前缀和得到。
接下来需要求出 maxa,b{Sa+Sb−ab},考虑固定 a,发现只有在凸包上的 b 有用,反之亦然。因此只保留凸包上的点,继而可以双指针。
时间复杂度 O(n)。
C:
发现每次可以通过添加两个数,使得方案数 ×2 或 ×2+1,这样可以拿到 60pts,打表 + 预处理可以优化成 75pts。
考虑构造如下由两部分组成的方案结构:
-
序列 (ai)i=1n,满足 ai>0。
-
序列 (−bi)i=1m,满足 bi>2∑ai。
这个方案的零和子集一定是空集或选出一些 ai 使得他们的和是某个 bj,由这些形成 ai 和形成的 bj 的集合,因此如果固定 a,每个 bi 的贡献是独立的。
考虑令 a 为某个优秀的常序列,预处理出每个 x 如果加进 b 中会对答案产生多少贡献,这可以通过背包求出,接下来考虑对于每个目标零和子集数求出方案,这同样可以用背包求出。
选择一个比较随机的 a 序列可以通过,时间复杂度为 O(106×22)。