Trick-整除分块(数论分块)

整除分块:

对于类似于 \(solve_{d=1}^{n}(\frac{n}{d})\) 的式子, \(\frac{n}{d}\) 的值的个数不超过 \(\sqrt n\) 个(下面有证明),故可以对于每一个结果去计算其贡献。

代码如下:

for(int l = 1, r; l <= n; l = r + 1) {
   r = n / (n / l);// d 在区间 [l, r] 的 n/d 大小相同
   ans += n / l * solve(l, r);
}

复杂度证明:

\(\dfrac{n}{d}\)\(x\)\(x\) 的取值范围在 \([1,n]\)。容易发现,\([1,\sqrt n]\) 的x更密集,\((\sqrt n, n]\)\(x\) 更稀疏。

因为 \(d\)\(1\)\(n\) ,只有 \(d\)\([1, \sqrt n]\) 时,\(\dfrac{n}{d}\)\((\sqrt n, n]\),所以\(\dfrac{n}{d}\)\((\sqrt n, n]\) 的个数不超过 \(\sqrt n\).

\(\dfrac{n}{d}\)\(1\)\(\sqrt n\) 一共 \(\sqrt n\) 个数,所以总个数为 \(O(\sqrt n)\) 的,本质上就是一个根号分治的思想。

一般式子中出现下取整,并且是分母一直在变,直接无脑整除分块。(P.S. 如果是分子在变,可以考虑类欧或万欧,分子分母都在变,可以考虑是否可让一个不变)

\(solve_{d=1}^{n}(\frac{a}{d}\frac bd)\) 这种式子也可以整除分块。

	for(int l = 1, r; l <= n; l = r + 1) {
		r = min({n, a / (a / l), b / (b / l)});
		ans = ans + 1ll * (b / l) * (a / l) * (sm[r] - sm[l - 1]);
	}

复杂度 \(O(\sqrt n)\)

这相当于在数轴上对 \(a\)\(O(\sqrt n)\) 个点,对 \(b\)\(O(\sqrt n)\) 个点,加起来还是 \(O(\sqrt n)\) 个点。

posted @ 2024-11-28 19:07  花子の水晶植轮daisuki  阅读(16)  评论(0)    收藏  举报
https://blog-static.cnblogs.com/files/zouwangblog/mouse-click.js