Skip to content

Latest commit

 

History

History

1862.Sum-of-Floored-Pairs

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 

1862.Sum-of-Floored-Pairs

首先,题目中计算任意两个元素之间的floor div,意味着数组里面的元素顺序并没有任何意义。我们可以任意选定一个元素i作为分母,考虑其他元素j做分子进行除法的结果。

显然,对于比nums[i] = x小的元素做分子,结果都是零,没有意义。我们只关心那些比x大的元素。我们知道,数值位于区间[x*k, x*(k+1)-1]的元素作为分子(k=1,2,3...),除法的结果就是k。自然地我们想知道数值位于该区间的元素多少?我们发现数组元素的数值大小的上限是100000,联想到桶排序,我们只需预处理nums,将每个元素的频次统计在桶计数器count里。这样,如果想知道位于某个数值范围[l,r]内的nums元素共有多少个,只需要用count的前缀和相减即可,这里记做presum[r]-presum[l-1]。

最终的解法是:对于x,我们从小到大遍历所有的k。令c = presum[x*(k+1)-1] - presum[x*k-1]代表了有多少元素与x的商恰好是k,那么最终答案就可以加上c*k. 特别注意,k的遍历的上界可能会使得x*(k+1)-1超过100000(桶的个数)。所以最后一段区间是一个“零头”,需要单独处理[x*k, 100000]

此外本题比较有趣的是对时间复杂度的分析。对于一个元素x,我们需要遍历的区间个数就是10^5/x个。本题最坏的情况是,所有的元素都不一样(x=1,2,3...),那么我们就没有任何可以重复利用的信息,那么最坏需要遍历的总次数就是10^5/1 + 10^5/2 + 10^5/3 ... ,即10^5 * (1/1 + 1/2 + 1/3 + ... 1/N)。后半部分是注明的调和级数,它是发散的,但是有渐近线,趋向于log(N),证明见这里。所以总的额时间复杂度就是o(10^5*logN).