数论分块&&P2261 [CQOI2007]余数求和

Label

数论分块

Description

给定正整数 n , k ( n , k ≤ 1 0 9 ) n,k(n,k\le10^9) n,k(n,k109),求 ∑ i = 1 n k \sum_{i=1}^{n}k i=1nk m o d mod mod i i i

Solution

前置引理:

引理1: ∀ a , b , c ∈ Z , ⌊ a b c ⌋ = ⌊ ⌊ a b ⌋ c ⌋ \forall a,b,c\in \Z,\lfloor\frac{a}{bc}\rfloor=\lfloor\frac{\lfloor\frac{a}{b}\rfloor}{c}\rfloor a,b,cZ,bca=cba

(此处没用到,以后推式子会用)

引理2: ∀ n ∈ N + , ∣ { ⌊ n d ⌋ ∣ d ∈ N + , d ≤ n } ∣ ≤ 2 n \forall n\in\N^{+},|\{\lfloor\frac{n}{d}\rfloor|d\in \N^+,d\le n\}| \le2\sqrt n nN+,{dndN+,dn}2n

证明:对于 d ≤ ⌊ n ⌋ , ⌊ n d ⌋ d\le\lfloor\sqrt n\rfloor,\lfloor\frac{n}{d}\rfloor dn ,dn至多有 n \sqrt n n 种取值;而对于 d > n d>\sqrt n d>n ,此时有 ⌊ n d ⌋ ≤ n \lfloor\frac{n}{d}\rfloor\leq\sqrt n dnn ,最多也只有 n \sqrt n n 种取值,证毕。

数论分块

数论分块一般用来解决含有 ⌊ n i ⌋ \lfloor\frac{n}{i}\rfloor in的求和式子。对于任意一个 i i i,我们需要 O ( 1 ) O(1) O(1)求出最大的 j j j使得 ⌊ n i ⌋ = ⌊ n j ⌋ \lfloor\frac{n}{i}\rfloor=\lfloor\frac{n}{j}\rfloor in=jn

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

引理 3 3 3:设 ⌊ n i ⌋ = k \lfloor\frac{n}{i}\rfloor=k in=k,则 m a x { j ∣ ⌊ n j ⌋ = k } = ⌊ n ⌊ n i ⌋ ⌋ max\{j|\lfloor\frac{n}{j}\rfloor=k\}=\lfloor\frac{n}{\lfloor\frac{n}{i}\rfloor}\rfloor max{jjn=k}=inn

证明: ⌊ n i ⌋ = k ↔ k ≤ n i < k + 1 ↔ n k + 1 < i ≤ n k \lfloor\frac{n}{i}\rfloor=k\leftrightarrow k\leq\frac{n}{i}<k+1\leftrightarrow \frac{n}{k+1}<i\leq\frac{n}{k} in=kkin<k+1k+1n<ikn

又由于 i i i为正整数,故 i ≤ n k ↔ i ≤ ⌊ n k ⌋ = ⌊ n ⌊ n i ⌋ ⌋ i\leq \frac{n}{k}\leftrightarrow i\leq\lfloor\frac{n}{k}\rfloor=\lfloor\frac{n}{\lfloor\frac{n}{i}\rfloor}\rfloor iknikn=inn,所以 i i i的取值上界为 ⌊ n ⌊ n i ⌋ ⌋ \lfloor\frac{n}{\lfloor\frac{n}{i}\rfloor}\rfloor inn

利用引理2、3,我们可以 O ( n ) O(\sqrt n) O(n ) [ 1 , n ] [1,n] [1,n]分成大约 2 n 2\sqrt n 2n 块,每一块 O ( 1 ) O(1) O(1)求和即可。

对于此题

∑ i = 1 n k \sum_{i=1}^{n}k i=1nk m o d mod mod i i i = ∑ i = 1 n ( k − i ⌊ k i ⌋ ) = n k − ∑ i = 1 n i ⌊ k i ⌋ =\sum_{i=1}^{n}(k-i\lfloor\frac{k}{i}\rfloor)=nk-\sum_{i=1}^{n}i\lfloor\frac{k}{i}\rfloor =i=1n(kiik)=nki=1niik

对于 ∑ i = 1 n i ⌊ k i ⌋ \sum_{i=1}^{n}i\lfloor\frac{k}{i}\rfloor i=1niik,由于分块后每块对应区间内 ⌊ k i ⌋ \lfloor\frac{k}{i}\rfloor ik值不变,故等差数列求和后乘以 ⌊ k i ⌋ \lfloor\frac{k}{i}\rfloor ik便是此分块对答案的贡献。

算法时间复杂度 O ( n ) O(\sqrt n) O(n )

拓展:二维数论分块

∑ i = 1 m i n ( m , n ) ⌊ m i ⌋ ⌊ n i ⌋ \sum_{i=1}^{min(m,n)}\lfloor\frac{m}{i}\rfloor\lfloor\frac{n}{i}\rfloor i=1min(m,n)imin

此时将代码中 r = n/(n/i)替换成 r = min(n/(n/i), m/(m/i))即可(此时划分的块区间内 ⌊ m i ⌋ , ⌊ n i ⌋ \lfloor\frac{m}{i}\rfloor,\lfloor\frac{n}{i}\rfloor im,in值显然不变,最多分成 4 n 4\sqrt n 4n 块)。

Code

#include<cstdio>
#include<iostream>
#define ri register int
#define ll long long
using namespace std;

ll n,k,l,r,ans;

int main()
{
	std::ios::sync_with_stdio(false);
	cin>>n>>k;
	l=1,ans=n*k;
	while(l<=n)
	{
		if(k/l==0) break;
		r=k/(k/l);
		if(r>n) r=n;
		ans-=(k/l)*(r*(r+1)/2-l*(l-1)/2);
		l=r+1;//分块时块的划分的移动
	}
	cout<<ans;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值