线性筛板子
const int N = 1e6+10;
int phi[N], mu[N], p[N], cnt, vis[N];
void init() {
phi[1] = mu[1] = 1;
for (int i=2; i
$O(nloglogn)$求$g=\mu * f$ 板子
void calc(int n, int *f, int *g) {
REP(i,1,n) g[i] = f[i];
REP(i,1,cnt) PER(j,1,n/p[i]) g[j*p[i]] -= g[j];
}
整除分块板子, 优化了一下除法次数
int mx = sqrt(n);
REP(i,1,mx) ans += (ll)(s[i]-s[i-1])*f(n/i);
for (int i=mx+1,j,k=n/i; i<=n; i=j+1,--k) {
j = n/k;
ans += (ll)(s[j]-s[i-1])*f(k);
}
练习1. luogu P2257 YY的GCD
大意: 求$\sum\limits_{i=1}^n \sum\limits_{j=1}^m[gcd(i,j)为素数]$
这种反演题目一般都是先转化为某个$g$函数的卷积, 再交换求和次序.
设$f(x)=[x为素数]$, $g=\mu *f=\sum\limits_{p|n}\mu(\frac{n}{p})$, 则有
$\begin{align*} \sum\limits_{i=1}^n \sum\limits_{j=1}^mf(gcd(i,j)) &= \sum\limits_{i=1}^n \sum\limits_{j=1}^m \sum\limits_{d|gcd(i,j)} g(d) \\ &= \sum\limits_{d=1}^{min(n,m)}g(d)\sum\limits_{i=1}^n\sum\limits_{j=1}^m [d|gcd(i,j)] \\ &= \sum\limits_{d=1}^{min(n,m)}g(d) \lfloor \frac{n}{d} \rfloor \lfloor \frac{m}{d} \rfloor \end{align*}$
所以求出$g$以后整除分块即可, 考虑如何求$g$, $O(nloglogn)$当然很容易求出
这里思考一下$O(n)$的求法
对于$g(x)$, 假设$y$为$x$的最小素因子, 即$x=iy$
若$x$为素数, 显然有$g(x)=\mu(1)=1$
若$i%y==0$, $g(x)=\mu(i)$
若$i%y!=0$, $g(x)=-g(i)+mu(i)$
欧拉筛一次即可$O(n)-O(q\sqrt{n})$
const int N = 1e7+10;
int mu[N], p[N], cnt, vis[N], g[N];
void init() {
mu[1] = 1;
for (int i=2; im) swap(n,m);
int lim = min(int(sqrt(n)*2),n);
REP(i,1,lim) ans+=(ll)(g[i]-g[i-1])*(n/i)*(m/i);
for (int i=lim+1,j; i<=n; i=j+1) {
j = min(n/(n/i),m/(m/i));
ans+=(ll)(g[j]-g[i-1])*(n/i)*(m/i);
}
printf("%lld\n", ans);
}
}
练习2. Luogu P4213 杜教筛
大意: 求$\sum\limits_{i=1}^{n}\varphi(i),\sum\limits_{i=1}^{n}\mu(i)$
杜教筛是用来求一类积性函数前缀和的算法, 核心思想是利用公式
$$g(1)S(n)=\sum\limits_{i=1}^n(f*g)(i)-\sum\limits_{i=2}^n g(i)S(\lfloor \frac{n}{i}\rfloor)$$
其中$S(n)$是我们要求的$f(n)$的前缀和, $g(n)$是我们需要构造的一个函数, 需要满足$f*g$和$g$的前缀和可以$O(1)$求出.
可以证明上面这个递归式调用的不同的$S(n)$不超过$2\sqrt{n}$个, 即
$$S(1),S(2),...,S(\sqrt{n}),S(\frac{n}{1}),S(\frac{n}{2}),...,S(\frac{n}{\sqrt{n}})$$
对于$i\le n^{\frac{2}{3}}$的$S(i)$, 先暴力求出.
而对于$i>n^{\frac{2}{3}}$的$S(i)$, 即$S(\frac{n}{1}),S(\frac{n}{2}),...,S(\frac{n}{n^{\frac{1}{3}}})$, 只有$n^{\frac{1}{3}}$项, 可以每一项$\sqrt{n}$求出
所以总复杂度为$O(n^{\frac{2}{3}})$
对于本题来说, 对于$\sum\limits_{i=1}^n\mu(i)$取$g=\boldsymbol 1$, 就有$f*g=\varepsilon$, 对于$\sum\limits_{i=1}^{n}\varphi(i)$同理
#include
#include
#include
#include
#include
#include
练习3. Luogu P3768 简单数学题
大意: 求$\sum\limits_{i=1}^n\sum\limits_{j=1}^nijgcd(i,j)$
又是个杜教板子题, 简单推一下.
$\begin{align*} \sum\limits_{i=1}^n\sum\limits_{j=1}^nijgcd(i,j) &= \sum\limits_{i=1}^n\sum\limits_{j=1}^nij\sum\limits_{d|gcd(i,j)} \varphi(d) \\&= \sum\limits_{d=1}^n\varphi(d)\sum\limits_{i=1}^n\sum\limits_{j=1}^nij[d|gcd(i,j)] \\ &= \sum\limits_{d=1}^nd^2\varphi(d)\sum\limits_{i=1}^{\lfloor \frac{n}{d}\rfloor}i\sum\limits_{j=1}^{\lfloor \frac{n}{d}\rfloor}j\end{align*}$
对这个式子用整除分块, 转化为求$\sum\limits_{i=1}^ni^2\varphi(i)$
按照杜教的套路, 这里可以凑一个函数$g=Id^2$, 这样$f*g=Id^3$, 总的复杂度仍然是$O(n^{\frac{2}{3}})$
const int N2 = 5e6+10, N3 = 2500;
int P, inv6, inv2, cnt;
int phi[N2], vis[N2], p[N2];
int S1[N2], S2[N3], v[N3];
ll N;
ll inv(ll x){return x<=1?1:inv(P%x)*(P-P/x)%P;}
void init(int n) {
phi[1] = 1;
REP(i,2,n-1) {
if (!vis[i]) p[++cnt]=i,phi[i]=i-1;
for (int j=1,t;j<=cnt&&i*p[j]<=n; ++j) {
vis[t=i*p[j]]=1;
if (i%p[j]==0) {phi[t]=phi[i]*p[j];break;}
phi[t]=phi[i]*phi[p[j]];
}
}
REP(i,1,n) S1[i]=(S1[i-1]+(ll)i*i%P*phi[i]%P)%P;
}
ll sqr(ll n) {n%=P;return n*n%P;}
ll s_1(ll n) {n%=P;return n*(n+1)%P*inv2%P;}
ll s_2(ll n) {n%=P;return n*(n+1)%P*(2*n+1)%P*inv6%P;}
ll s_3(ll n) {n%=P;return sqr(s_1(n));}
int sum(ll n) {
if (n
练习4. luogu P3172 [CQOI2015]选数
大意: 求选择$n$个范围[L,R]的数, 且$gcd=k$的方案数
相当于求$\sum\limits_{L\le a_1 \le R}\cdots\sum\limits_{L\le a_n \le R}[gcd=k]$
等价于$\sum\limits_{l\le a_1 \le r}\cdots\sum\limits_{l\le a_n \le r}[gcd=1]$, 其中$l=\lfloor \frac{L-1}{K}\rfloor+1, r=\frac{R}{K}$
再反演一下就没了.....$\sum\limits_{d=1}^{r}\mu(d)(\lfloor \frac{r}{d}\rfloor-\lfloor \frac{l-1}{d} \rfloor)^n$
这题因为有$\lfloor \frac{r}{d}\rfloor$和$\lfloor \frac{l-1}{d} \rfloor$两部分, 所以为了方便直接用map记忆化了
这题刚开始想错了, 反演成$\varphi$了, 结果改了半天................
const int N2 = 2e6+10, N3 = 2000, P = 1e9+7;
int mu[N2], vis[N2], p[N2];
int n, k, l, r, cnt;
unordered_map S2;
ll qpow(ll a,ll n) {ll r=1%P;for (a%=P;n;a=a*a%P,n>>=1)if(n&1)r=r*a%P;return r;}
void init(int n) {
mu[1] = 1;
REP(i,2,n-1) {
if (!vis[i]) p[++cnt]=i,mu[i]=-1;
for (int j=1,t;j<=cnt&&i*p[j]<=n; ++j) {
vis[t=i*p[j]]=1;
if (i%p[j]==0) {mu[t]=0;break;}
mu[t] = -mu[i];
}
mu[i] += mu[i-1];
}
}
int sum(int n) {
if (n
练习5. Luogu P3327 [SDOI2015]约数个数和
大意: 求$\sum\limits_{i=1}^n\sum\limits_{j=1}^md(ij)$, $d(n)$为除数函数
对于除数函数可以这样处理$d(ij)=\sum\limits_{x|i}\sum\limits_{y|i}[x\perp y]=\sum\limits_{x|i}\sum\limits_{y|i}\sum\limits_{d|gcd(x,y)}\mu(d)$
所以就可以得到$\sum\limits_{i=1}^n\sum\limits_{j=1}^md(ij)=\sum\limits_{d=1}^{min(n,m)}\varphi(d)\sum\limits_{i=1}^{\lfloor \frac{n}{d}\rfloor}\lfloor \frac{n}{id} \rfloor \sum\limits_{j=1}^{\lfloor \frac{m}{d}\rfloor}\lfloor \frac{m}{jd} \rfloor$
然后就没了....主要这题的数据范围太小, 不需要杜教筛也行