浅谈整除分块

例题一

∑ i = 1 n ⌊ n i ⌋ \sum_{i=1}^n \lfloor\frac n i\rfloor\\ i=1nin

首先很容易想到直接求解,对于较大的数据, O ( n ) O(n) O(n)做法无法通过。

注意到函数 y = ⌊ n x ⌋ y=\lfloor\dfrac n x\rfloor y=xn的图像如下:

不难发现,随着 x x x 增大 , y y y单调不增,这说明对于相同值的 y y y 总是分布在同一块区域。

这启发我们根据 y y y值,把 x x x分组,每组“打包”算好。

这个时间复杂度显然是 O ( n ) O(\sqrt n) O(n )的,时间复杂度与 ⌊ n x ⌋ \lfloor\dfrac n x\rfloor xn的数量有关,这个数量大概是 2 n 2\sqrt n 2n

虽然图像上看 y y y的数量很大,但是考虑到许多 y y y不包含整数的 x x x,因此时间复杂度就是这样的了。

代码实现如下:

for(LL l=1,r;l<=n;l=r+1)
{
   r=n/(n/l);
   ans+=(n/l)*(r-l+1);
}

例题二

∑ i = 1 n k   m o d   i \sum_{i=1}^nk\bmod i\\ i=1nkmodi

对原式进行推导:

∑ i = 1 n k   m o d   i = ∑ i = 1 n k − i ⌊ k i ⌋ = n k − ∑ i = 1 n i ⌊ k i ⌋ \sum_{i=1}^nk\bmod i\\ =\sum_{i=1}^nk-i\lfloor\frac k i\rfloor\\ =nk-\sum_{i=1}^ni\lfloor\frac k i\rfloor\\ i=1nkmodi=i=1nkiik=nki=1niik

后面的部分可以用整除分块解决,对于每个 ⌊ n i ⌋ \lfloor \dfrac n i\rfloor in,内部相当于一个等差数列。

代码实现如下:

ans=n*k;
for(LL l=1,r;l<=n&&l<=k;l=r+1)
{
    r=min(k/(k/l),n);
    ans-=(k/l)*(r+l)*(r-l+1)/2;
}

例题三

函数 f ( i ) f(i) f(i) 表示 i i i 所有约数的和。

∑ i = L R f ( i ) \sum\limits_{i=L}^R f(i) i=LRf(i)

考虑前缀和作差,问题变成 [ 1 , R ] − [ 1 , L − 1 ] [1,R]-[1,L-1] [1,R][1,L1]

于是不难列出式子求解,与上一题很像。

例题四

∑ i = 1 n ∑ j = 1 m ( n   m o d   i ) ( m   m o d   j ) \sum_{i=1}^n\sum_{j=1}^m (n\bmod i)(m\bmod j)\\ i=1nj=1m(nmodi)(mmodj)

这道题显然也是推导。

∑ i = 1 n ∑ j = 1 m ( n   m o d   i ) ( m   m o d   i ) = ∑ i = 1 n ( n   m o d   i ) ∑ j = 1 m ( m   m o d   j ) = ∑ i = 1 n ( n − i ⌊ n i ⌋ ) ∑ j = 1 m ( m − j ⌊ m j ⌋ ) = ( n 2 − ∑ i = 1 n i ⌊ n i ⌋ ) ( m 2 − ∑ j = 1 m m ⌊ m j ⌋ ) \sum_{i=1}^n\sum_{j=1}^m (n\bmod i)(m\bmod i)\\ =\sum_{i=1}^n(n\bmod i)\sum_{j=1}^m (m\bmod j)\\ =\sum_{i=1}^n(n-i\lfloor\frac n i\rfloor)\sum_{j=1}^m (m-j\lfloor\frac m j\rfloor)\\ =(n^2-\sum_{i=1}^n i\lfloor\frac n i\rfloor)(m^2-\sum_{j=1}^m m\lfloor\frac m j\rfloor)\\ i=1nj=1m(nmodi)(mmodi)=i=1n(nmodi)j=1m(mmodj)=i=1n(niin⌋)j=1m(mjjm⌋)=(n2i=1niin⌋)(m2j=1mmjm⌋)

左右两边分开计算即可。

例题五

∑ i = 1 n ( n   m o d   i ) ( m   m o d   i ) \sum_{i=1}^n (n\bmod i)(m\bmod i)\\ i=1n(nmodi)(mmodi)

和上道题看着很像,不过这道题就很复杂了。

∑ i = 1 n ( n   m o d   i ) ( m   m o d   i ) = ∑ i = 1 n ( n − i ⌊ n i ⌋ ) ( m − i ⌊ m i ⌋ ) = ∑ i = 1 n ( n m − ( n + m ) i ⌊ n i ⌋ + i 2 ⌊ n i ⌋ ⌊ m i ⌋ ) = n 2 m − ( n + m ) ∑ i = 1 n i ⌊ n i ⌋ + ∑ i = 1 n i 2 ⌊ n i ⌋ ⌊ m i ⌋ \sum_{i=1}^n (n\bmod i)(m\bmod i)\\ =\sum_{i=1}^n (n-i\lfloor\frac n i\rfloor)(m-i\lfloor\frac m i\rfloor)\\ =\sum_{i=1}^n (nm-(n+m)i\lfloor\frac n i\rfloor+i^2\lfloor\frac n i\rfloor\lfloor\frac m i\rfloor)\\ =n^2m-(n+m)\sum_{i=1}^n i\lfloor\frac n i\rfloor+\sum_{i=1}^n i^2\lfloor\dfrac n i\rfloor\lfloor\frac m i\rfloor\\ i=1n(nmodi)(mmodi)=i=1n(niin⌋)(miim⌋)=i=1n(nm(n+m)iin+i2inim⌋)=n2m(n+m)i=1niin+i=1ni2inim

前面的式子我们已经可以轻松求出了,对于后面的这个东西,我们还是画图观察:

显而易见,仍然满足我们刚开始的两个性质,因此依旧使用之前的方式进行整除分块,时间复杂度依旧是 O ( n ) O(\sqrt n) O(n )

具体思想如下:

我们的值变化,要么是因为 ⌊ n x ⌋ \lfloor\dfrac n x\rfloor xn 变化了,要么是因为 ⌊ m x ⌋ \lfloor\dfrac m x\rfloor xm 变化了。

因此找出 ⌊ n x ⌋ \lfloor\dfrac n x\rfloor xn 变化的点和 ⌊ m x ⌋ \lfloor\dfrac m x\rfloor xm 变化的点中最近的一个,作为我们的 r r r 值。

后面部分的代码实现如下:

for(LL l=1,r=0;l<=n;l=r+1)
{
    r=min(n/(n/l),m/(m/l));
    ans=ans+(n/l)*(m/l)*(sum(r)-sum(l-1));
}

这里出现了一个函数,它的作用是求出: s u m i = ∑ i = 1 n i 2 sum_i=\sum\limits_{i=1}^ni^2 sumi=i=1ni2

公式是 ∑ i = 1 n i 2 = n ( n + 1 ) × ( 2 n + 1 ) 6 \sum\limits_{i=1}^ni^2=\dfrac {n(n+1)\times(2n+1)} 6 i=1ni2=6n(n+1)×(2n+1),用数学归纳法很好证明,这里不多赘述了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值