整除分块

前置芝士

整除分块

性质

(1)对于\(g(x)=\lfloor\frac nx\rfloor\)(其中 x为正整数,且 1≤x≤n),则 g(x) 不同值的个数不会超过 \(2\sqrt{n}\) 个,故时间复杂度为\(\sqrt{n}\)

[证明]

\(x\leq\sqrt{n}\)时,直接枚举\(\sqrt{n}\)个数,区间长度为1,即[x,x]。

\(x>\sqrt{n}\)时,可以推导出:\(g(x)=\lfloor\frac nx\rfloor\leq\frac nx<\sqrt{n}\)

(2)g(x)单调不增

(3)整数分块中,值相同的一定是连续的,所以对于每个 g(x) 的值我们只需要知道一个区间即可。

\[\text{设}\left\lfloor\frac N{i^{\prime}}\right\rfloor\text{与}\left\lfloor\frac Ni\right\rfloor\text{相等,则}i^{\prime}\text{ 的最大值为}\left\lfloor\frac N{\left\lfloor\frac Ni\right\rfloor}\right\rfloor \]

[证明]

\[\begin{aligned}&\text{设}\left\lfloor\frac Ni\right\rfloor=k\text{ ,于是可以写成 }ki+p=N,1\leq p<i\text{ 的形式,若}\left\lfloor\frac N{i+d}\right\rfloor=k\text{ ,于是有 }k(i+d)+p^{\prime}=N\text{ ,可以得到 }p^{\prime}=p-kd,\text{则 }d\text{ 能取的}\\&\text{最大值为}\left\lfloor\frac pk\right\rfloor,\text{于是:}\end{aligned} \]

\[\begin{aligned} i'& =i+d_{max} \\ &=i+\lfloor\frac pk\rfloor \\ &=i+\left\lfloor\frac{N\textit{ mod i}}{ \lfloor \frac N i \rfloor }\right\rfloor \\ &=i+\left\lfloor\frac{N-\lfloor\frac Ni\rfloor i}{\lfloor\frac Ni\rfloor}\right\rfloor \\ &=\left\lfloor i+\frac{N-\lfloor\frac Ni\rfloor i}{\lfloor\frac Ni\rfloor}\right\rfloor \\ &=\left\lfloor\frac{\lfloor\frac Ni\rfloor i}{\lfloor\frac Ni\rfloor}+\frac{N-\lfloor\frac Ni\rfloor i}{\lfloor\frac Ni\rfloor}\right\rfloor \\ &=\left\lfloor\frac N{\lfloor\frac Ni\rfloor}\right\rfloor\quad\end{aligned} \]

约数研究

[problem presection]

统计每个正数 \(N\) 的约数的个数,并以 \(f(N)\) 来表示。例如 \(12\) 的约数有 \(1,2,3,4,6,12\),因此 \(f(12)=6\)。下表给出了一些 \(f(N)\) 的取值:

\(N\) \(1\) \(2\) \(3\) \(4\) \(5\) \(6\)
\(f(N)\) \(1\) \(2\) \(2\) \(3\) \(2\) \(4\)

现在请你求出:

\[\sum_{i=1}^n f(i) \]

[input]

输入一个整数 \(n\)

[output]

输出一行一个整数表示答案。

\(1 \leq N \leq 10^6\)

[solved]

约数的性质:

每个正约数i在 1 ~ n 中出现的次数为\(\left\lfloor\frac ni\right\rfloor\),问题转换成求\(\sum_{i=1}^{n}\left|{\frac{n}{i}}\right|\)的值,套用整除分块模板即可。

int n,res=0;
void solve(){
		cin>>n;
		for(int l=1,r;l<=n;l=r+1){
			r=n/(n/l);
			res+=n/l*(r-l+1);
		}
		cout<<res<<endl;
}

约数和

[problem presection]

对于一个数 \(X\),函数 \(f(X)\) 表示 \(X\) 所有约数的和。例如:\(f(6)=1+2+3+6=12\)。对于一个 \(X\),Smart 可以很快的算出 \(f(X)\)。现在的问题是,给定两个正整数 \(X,Y(X<Y)\),Smart 希望尽快地算出 \(f(X)+f(X+1)+……+f(Y)\)的值,你能帮助 Smart 算出这个值吗?

[input]

输入文件仅一行,两个正整数 \(X\)\(Y(X<Y)\),表示需要计算 \(f(X)+f(X+1)+\dots +f(Y)\)

[output]

输出只有一行,为 \(f(X)+f(X+1)+\dots+f(Y)\) 的值。

\(1\leq X<Y\leq 2\times 10^9\)

[solved]

能得到每个正约数i在 1 ~ n 中出现的次数为\(\left\lfloor\frac{n}{i}\right\rfloor\),那么每个约数对总和的贡献就为\(i*\left\lfloor{\frac{n}{i}}\right\rfloor\),问题就转化为求\(\sum_{i=1}^{n}i*\left\lfloor{\frac{n}{i}}\right\rfloor\),可以分块处理了。

对于每块[l,r]的\(\left\lfloor\frac{n}{i}\right\rfloor\)值是相同的,可以认为一个常数,每块的计算就相当于求\(\left\lfloor{\frac{n}{l}}\right\rfloor\sum_{i=l}^{r}i\),这个用等差数列的求和就能够很轻易地得到答案。

求f[X,Y]区间的答案,可以转化为f[1,Y]-f[1,X-1]。

ll X,Y;
ll f(ll n){
	ll res=0;
	for(ll l=1,r;l<=n;l=r+1){
		r=n/(n/l);
		res+=(1ll)*(n/l)*(r-l+1)*(l+r)/2;
	}
	return res;
}
void solve(){
	cin>>X>>Y;
	cout<<f(Y)-f(X-1)<<endl;
}

余数求和

[problem presection]

给出正整数 \(n\)\(k\),请计算

\[G(n, k) = \sum_{i = 1}^n k \bmod i \]

其中 \(k\bmod i\) 表示 \(k\) 除以 \(i\) 的余数。

[input]

输入只有一行两个整数,分别表示 \(n\)\(k\)

[output]

输出一行一个整数表示答案。

\(1 \leq n, k \leq 10^9\)

[solved]

[公式推导]

\[\begin{aligned} \sum_{i=1}^n(kmodi)& =\sum_{i=1}^n(k-i\lfloor\frac ki\rfloor) \\ &=\sum_{i=1}^nk-\sum_{i=1}^ni\lfloor\frac ki\rfloor \\ &=nk-\sum_{i=1}^ni\lfloor\frac ki\rfloor \end{aligned} \]

[注意事项]

当k/i=0时,随着i的增加,k/i始终为0,因此需要退出分块计算,或者在计算r时会出现分母为0的情况,导致程序出错。

需要注意分到最后一块时,计算出来的右边界可能会超出n,此时右边界就是n,进行取min操作就行了。

ll n,k;
void solve(){
	cin>>n>>k;
	ll res=n*k;
	for(ll l=1,r;l<=n;l=r+1){
		if(k/l==0) break;
		r=min(n,k/(k/l));
		res-=k/l*(l+r)*(r-l+1)/2;
	}
	cout<<res<<endl;
}

Floor and Mod

[problem presection]

A pair of positive integers \((a,b)\) is called special if \(\lfloor \frac{a}{b} \rfloor = a \bmod b\). Here, \(\lfloor \frac{a}{b} \rfloor\) is the result of the integer division between \(a\) and \(b\), while \(a \bmod b\) is its remainder.

You are given two integers \(x\) and \(y\). Find the number of special pairs \((a,b)\) such that \(1\leq a \leq x\) and \(1 \leq b \leq y\).

[input]

The first line contains a single integer \(t\) (\(1 \le t \le 100\)) — the number of test cases.

The only line of the description of each test case contains two integers \(x\), \(y\) (\(1 \le x,y \le 10^9\)).

[output]

For each test case print the answer on a single line.

[solved]

[公式推导]

。。。。。。

posted @ 2023-10-16 13:00  White_Sheep  阅读(4)  评论(0编辑  收藏  举报