首先这里暴力算法指的是:
CPP
for(k=3;k<=n;k++) for(i=k;i<=n;i++) if(a[i]<s[i-1]-s[i-k]) {
cout<<k<<' ';break;
}
或者类似的东西。
可以证明除排序部分之外剩下的复杂度是
O(n+log2(maxa))。
对于每个“循环次数大于一”的
k,都有
a1+a2+⋯+ak−1≤ak。所以把这些
ak 排成一个序列,就会发现序列中每一项都大于等于前面所有项的和。故由归纳法易证序列的第
i(i≥2) 项至少是
2i−2。从而这样的
k 最多有
O(log(maxa)) 个。
对于每个
k,假设
break 语句在
i=i(k)+1 时执行。如果一直没有执行,则令
i(k)=n。
这样就会得到:
a1+⋯+ak−1≤ak,a2+⋯+ak≤ak+1,以此类推直到
ai(k)。
因为所有
a 都是正的,所以在左边去掉若干项,不等式仍然成立。
所以当
i(k)<2k 时,可以发现:
ak≤ak+1,ak+ak+1≤ak+2,以此类推直到
ak+ak+1+⋯+ai(k)−1≤ai(k)。
所以这个序列:
ak,ak+1,ak+2,⋯,ai(k)
它也满足“每一项都大于等于前面所有项的和”,所以同样有第
i(i≥2) 项不小于
2i−2。从而
ai(k) 是
2i(k)−k 量级,
i(k)−k=O(log(maxa))。
如果
i(k)≥2k,刚才的结论仍然对于
2k−1 适用,即
a2k−1≥2k−2。于是从
a2k−1 开始再构造若干类似刚才的序列,直到
ai(k)。就会发现它依然是
2i(k)−k 量级。
所以还是有
i(k)−k=O(log(maxa))。
综上,每个
k 对应的循环次数最多是
O(log(maxa))。
这样最开始的结论就证出来了。(因为不算太严谨,而且有点啰嗦,所以就发在讨论区了)