超绝值域分治。
考虑
n≤42 时,我们可以暴力 meet-in-the-middle,把
n 个数分成个数尽量相等的两堆,每堆里枚举子集,把该子集中数的和记录在一个哈希表中。然后枚举第一堆的哈希表里的值
x,查询第二堆的哈希表中是否存在
s−x。若存在则输出。复杂度
O(22n)(使用
unordered_map,近似
O(1))。
若
n>42,则根据题面中给定的
{a} 的生成方式,不难得出结论:
a1≤264−n≤264−43=221。那么我们枚举真正的
a1 的复杂度是可以接受的。枚举
a1 后就能得到一系列可能的
r 使得
a1×r≡b1(mod264)。因为保证
r 和
264 互质,意味着
r 存在逆元,确定
r 后就能还原出整个
{a}。此时判定一下还原后的序列是否合法即可。若合法且存在解就输出(由于
a 的某一项必然大于前面的项的和,易证若有解必为唯一解,构造方式是从大往小贪心,如果能减就减)。
现在的问题在于求出一个
a1 对应的
r(们)。我们有式子:
a1×r≡b1(mod264)
设
b1=2k×p,其中
p 是奇数,那么此式等价于:
2ka1×r≡p(mod264−k)
这个式子告诉我们,
2k∣a1。因此合法的
a1=x×2k,x∈[1,264−n−k],只有
264−n−k 种。
由于我们想要从
{b} 还原出
{a},所以其实我们
只关心 r 的逆元 r−1 的值。将上式变形:
2ka1≡p×r−1(mod264−k)
r−1≡2ka1×p−1(mod264−k)
其中,
p 由
b1 确定,即是一个确切值;同时
p 一定是奇数,因此
p−1 一定存在且固定。
因此只要确定了
a1,就确定了
r−1mod264−k=2ka1×p−1。也即,
r−1=y×264−k+2ka1×p−1,y∈[0,2k)。
因此对于一个
a1,合法的
r 的数量是
2k 种。整体上合法的
(a1,r) 数对就只有
264−n−k×2k=264−n 种情况。每种情况在得到
r−1 后的判定是
O(n) 的,因此总复杂度为
O(n×264−n)。
在
42<n≤64 时,这个值在
n=43 时取极大值
43×221=90177536,是
9×107 的量级,常数较小的实现方式可以轻松通过。