前几天和同事聊天,聊到前几天的北京数学高考题。最后一个题还挺有意思的,我和同事 yy 了好久都不会:
给定两个序列 {ai},{bi}∈[n]n,证明存在四个正整数 la≤ra,lb≤rb 使得
i=la∑raai=i=lb∑rbbi.
在想这个题的时候,我想到了曾经做 POI 的时候见过的一个题:
给定一个大小为 n 的序列 a,其中 ai∈{1,2}。
现在有 m 个询问,每次给定一个 k,要你找出一个和为 k 的子段,或者输出不存在。
数据范围为 n≤107,k≤105。
高考题
定义 At=i=1∑tai 为 a 的前缀和,Bt 为 b 的前缀和。原题有一个提示:不妨令 An≤Bn,定义 ri=min{0≤j≤n:Ai≤Bj}。考虑 di=Bri−Ai,注意到当 ri>0 时有
B∗ri−1<Ai≤B∗ri,
故有 di<Bri−Bri−1≤n,而 ri=0 意味着 Ai=0,所以 i=0,而我们又有 d0=0,综上有:
∀0≤i≤n,0≤di<n.
由于我们有 n+1 个 di,但是不同的 di 只有 n 个,所以必定存在 di=dj,这也就意味着
B∗ri−Ai=B∗rj−Aj,
证毕。
POI
我看到这个题的第一反应是 FFT,但是 FFT 有三个缺点:
- 难写;
- 慢,这里 n 的范围是 107,FFT 估计太慢了;
- 最重要的一点,FFT 没法输出位置……
后来实在不会只好去看 tutorial,发现就一句话的事:
如果存在一个和为 k 的子段且 k>2,那么必定存在一个和为 k−2 的子段。
证明很简单,假设 [i,j] 的子段和为 k,我们考虑 ai 和 aj:
- 如果 ai=2,那么 [i+1,j] 满足要求;
- 如果 aj=2,那么 [i,j−1] 满足要求;
- 否则必定有 ai=aj=1,那么 [i+1,j−1] 满足要求。
于是,我们只要找到最大的和为奇数的子段和最大的和为偶数的子段即可。全序列肯定是其中一个,另一个就看第一个 1 和最后一个 1 出现的位置就可以了。