整除分块 学习笔记
过程
用来求求和符号内带有 \(\lfloor\frac{n}{i}\rfloor\) 的式子,例如 \(\sum_{i=1}^n f(i)\lfloor\frac{n}{i}\rfloor\)。
不难发现 \(\lfloor\frac{n}{i}\rfloor\) 的取值是成段的。当 \(i\leq\sqrt n\),取值不超过 \(\sqrt n\) 种,当 \(i>\sqrt n\),\(\lfloor\frac{n}{i}\rfloor\leq\sqrt n\)。因此总取值是根号级别的。
假设已知块左端点 \(l\),推出右端点 \(r\),在区间 \([l,r]\) 内 \(\lfloor\frac n i\rfloor\) 是相同的,那么式子就变成 \(\sum_{(l,r)}\lfloor\frac{n}{i}\rfloor\sum_{i=l}^rf(i)\),只需要快速计算 \(f\) 的前缀和即可。
引理:
现在推一下 \(r\):
因此 \(r=\lfloor\frac{n}{\lfloor\frac{n}{l}\rfloor}\rfloor\)。
for(int l=1,r;l<=n;l=r+1)r=n/(n/l),ans+=sum(l,r)*(n/l);
求 \(\sum_{i=1}^n k\bmod i\)。
推式子:
由于分子不到 \(n\),可能出现 \(\lfloor\frac{k}{l}\rfloor\) 为 \(0\),这样算 \(r\) 的时候会寄掉,此时直接给 \(r\) 赋值为 \(n\)。
#include<bits/stdc++.h>
using namespace std;
long long n,k,ans;
int main(){
cin>>n>>k;
for(long long l=1,r;l<=n;l=r+1)r=k/l?min(n,k/(k/l)):n,ans+=(k/l)*(r-l+1)*(l+r)/2;
return cout<<n*k-ans<<'\n',0;
}
高维整除分块
假如求和符号内同时有 \(\lfloor\frac{n}{i}\rfloor,\lfloor\frac{m}{i}\rfloor\),如果用整除分块,需要使得 区间 \([l,r]\) 内 \(\lfloor\frac{n}{i}\rfloor,\lfloor\frac{m}{i}\rfloor\) 都相等。此时,只需要让 \(r=\min(\lfloor\frac{n}{\lfloor\frac{n}{l}\rfloor}\rfloor,\lfloor\frac{m}{\lfloor\frac{m}{l}\rfloor}\rfloor)\) 即可。更高维类似。
复杂度证明:每一维一共有 \(O(\sqrt n)\) 个分界点,加在一起仍然是 \(O(\sqrt n)\) 个分界点。
推式子:
其中每部分都可以通过整除分块快速算。
#include<bits/stdc++.h>
using namespace std;
const long long mod=19940417;
long long n,m,t1,t2,t3;
int main(){
cin>>n>>m,t1=n*n%mod,t2=m*m%mod;
for(long long l=1,r;l<=n;l=r+1)r=n/(n/l),t1=(t1-(l+r)*(r-l+1)%mod*9970209%mod*(n/l)%mod+mod)%mod;
for(long long l=1,r;l<=m;l=r+1)r=m/(m/l),t2=(t2-(l+r)*(r-l+1)%mod*9970209%mod*(m/l)%mod+mod)%mod;
for(long long l=1,r;l<=min(n,m);l=r+1){
r=min(n/(n/l),m/(m/l));
t3=(t3+(r-l+1)*n%mod*m%mod)%mod;
t3=(t3-(l+r)*(r-l+1)%mod*9970209%mod*((n/l)*m%mod+(m/l)*n%mod)%mod+mod)%mod;
t3=(t3+(n/l)*(m/l)%mod*(r*(r+1)%mod*(2*r+1)%mod-(l-1)*l%mod*(2*l-1)%mod+mod)%mod*3323403%mod)%mod;
}
return cout<<(t1*t2%mod-t3+mod)%mod<<'\n',0;
}
高次整除分块
形如 \(\lfloor\frac{n}{i^k}\rfloor\) 的式子都可整除分块,取值共 \(\sqrt[k+1]{n}\) 种。此时右端点 \(r\) 为:
[[数学]]

浙公网安备 33010602011771号