POI X Sums
一个集合 SSS
内有 nnn
个正整数 {a1,a2,…,an}\{a_1, a_2, \ldots, a_n\}{a1,a2,…,an}
,S′S'S′
表示由集合 SSS
中的数相加所得的集合,每个数都可以用无数次。
有 qqq
次询问,询问一个 xxx
是否在 S′S'S′
内。存在输出 y
否则输出 n
。
n≤5000,q,ai,≤50000,x≤1017n \leq 5000, q, a_i, \leq 50000, x \leq 10^{17}n≤5000,q,ai,≤50000,x≤1017
.
输入 nnn
,然后输入 nnn
个数,再输入 qqq
,然后qqq
个 xxx
题意可以转化为:给定a数组,问式子a[1]*x[1]+a[2]*x[2]+……+a[n]*x[n]=k是否有正整数解。
其实看下来,这就是一个容量为k的完全背包,判断是否能恰好装满。
叉姐的解释:
在 SSS
中找一个数,例如 a1a_1a1
. 一个关键性质是:如果 x∈S′x \in S'x∈S′
,那么x+a1∈S′x + a_1 \in S'x+a1∈S′
.
那么设 d[r]d[r]d[r]
表示所有模 a1a_1a1
于 rrr
的数中,最小的 ∈S′\in S'∈S′
的数。根据性质,d[r],d[r]+a1,d[r]+2a1,…∈S′d[r], d[r] + a_1, d[r] + 2a_1, \ldots \in S'd[r],d[r]+a1,d[r]+2a1,…∈S′
. 同时因为 d[r]d[r]d[r]
是最小的,所以同余类中 <d[r]< d[r]<d[r]
的数都 ∉S′\notin S'∉S′
.
具体求 d[∗]d[*]d[∗]
的过程是最短路。首先,d[0]=0d[0] = 0d[0]=0
。其次,可以用d[x]+aid[x] + a_id[x]+ai
去更新 d[(x+ai) mod a1]d[(x + a_i)\ \mathrm{mod}\ a_1]d[(x+ai) mod a1]
.
这里如果用 Dijkstra 的话,复杂度是 O(na1loga1)O(na_1 \log{a_1})
. 从这个角度上讲,