[学习笔记]莫比乌斯反演

上接狄利克雷卷积&积性函数

一.莫比乌斯反演公式

$ $

$\qquad\qquad\qquad\qquad\qquad$ 设 $F(n) = \sum\limits_{d|n}f(d)$ ,那么有 $f(n) = \sum\limits_{d|n}\mu(d)F(\frac{n}{d})$

其中 $\mu(d)$ 是这样一个函数:

$\qquad$ $\mu(d)=\begin{cases} 1 , & d=1 \\  (-1)^{k} ,  & d=\prod\limits_{i=1}^k p_{i} , p_{i} \text{是互异的质数}  \\  0 , & \text{其它情况}  \end{cases}$

证明:根据原始 $F(x)$ 定义,$\sum\limits_{d|n}\mu(d)F(\frac{n}{d})$ $=$ $\sum\limits_{d|n}\mu(d)\sum\limits_{d'|\frac{n}{d}}f(d')$

$\qquad\;\;$ 然后根据乘法分配律,我们有 $\qquad\;\;\;=\sum\limits_{d'|n}f(d')\sum\limits_{d|\frac{n}{d'}}\mu(d)$

$\qquad\;\;$ 注意到 $\sum\limits_{d|\frac{n}{d'}}\mu(d)$ 这玩意仅当 $d' = n$ 时为 $1$ ,其余时候都为 $0$

$\qquad\;\;$ 那么 $d'$ 只能等于 $n$ ,原式自然退化成 $f(n)$

书上讲的是些什么东西

二. $\mu$ 函数的性质

  1. 当且仅当 $n = 1$ 时 $\sum\limits_{d|n}\mu(d) = 1$ ,其余情况下  $\sum\limits_{d|n}\mu(d) = 0$ ( $n$ 是正整数 )
  2. 对于任意正整数 $n$ 有 $\sum\limits_{d|n}\frac{\mu(d)}{d} = \frac{φ(n)}{n}$ ( $φ(n)$ 是欧拉函数 )

三.一些衍生公式

下方有大量 $\LaTeX$ 出没,加载可能较慢

$\;$

$\mathit{0.}$ 前导公式 $\quad\sum\limits_{d|k}[k = 1] = \sum\limits_{d|k}\mu(d)$

$\qquad$ 证明:据性质 $\mathit{1}$ 可得显然成立

$\mathit{0.5}$ 通式 $\quad\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}f(\gcd(i,j))$

$\qquad$ 证明:$\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}f(\gcd(i,j))=\sum\limits_{d=1}^{n}f(d)\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}[\gcd(i,j)=d]$

 

$\qquad\qquad\qquad\qquad\qquad\qquad\;$ $=\sum\limits_{d=1}^{n}f(d)\sum\limits_{i=1}^{\lfloor \frac{n}{d} \rfloor}\sum\limits_{j=1}^{\lfloor \frac{m}{d} \rfloor}[\gcd(i,j)=1]$

$\qquad\qquad\qquad\qquad\qquad\qquad\;$ $=\sum\limits_{d=1}^{n}f(d)\sum\limits_{k=1}^{\lfloor \frac{n}{d} \rfloor}\mu(k)\lfloor\frac{n}{dk}\rfloor\lfloor\frac{m}{dk}\rfloor$

$\qquad\qquad\;\;$ 不妨设 $dk=T$ 那么原式就是 $\sum\limits_{T=1}^{n}\lfloor\frac{n}{T}\rfloor\lfloor\frac{m}{T}\rfloor\sum\limits_{d|T}f(d)\mu(\frac{T}{d})$

$\qquad\qquad\;\;$ 数论分块可以 $\Theta(n)$ 处理, $\Theta(\sqrt{n})$ 查询

$\mathit{1.}$ 求互质数对数 $\quad\sum\limits_{i=1}^n\sum\limits_{j=1}^m$$[\gcd(i,j)=1]$ $=$ $\sum\limits_{d=1}^n$$\mu$$(d)$$\lfloor$$\frac{n}{d}$$\rfloor$$\lfloor$$\frac{m}{d}$$\rfloor$

$\qquad$ 证明$\quad\because\quad\sum\limits_{d|k}[k = 1] = \sum\limits_{d|k}\mu(d)$ ,我们用 $\gcd(i,j)$ 去替代 $k$

$\qquad\qquad\quad\;\;\,\therefore$ $\quad\sum\limits_{i=1}^n\sum\limits_{j=1}^m$$[\gcd(i,j)=1]$ $=$ $\sum\limits_{i=1}^n\sum\limits_{j=1}^m\sum\limits_{d|i,d|j}$$\mu(d)$ $\quad\gets$ 这里用了性质 $\mathit{1}$ ,当 $\gcd(i,j)=1$ 时 $\sum\limits_{d|i,d|j}$$\mu(d)$ 才不为 $0$

$\qquad\qquad\qquad\qquad\qquad\qquad\quad\qquad\;\;\;\,$ $=$ $\sum\limits_{i=1}^n\sum\limits_{j=1}^m\sum\limits_{d|\gcd(i,j)}$$\mu$$(d)$ $\quad\gets$ 这里比较显然,如果 $d$ 既是 $i$ 的因数又是 $j$ 的因数那么 $d$ 一定是 $\gcd(i,j)$ 的因数

$\qquad\qquad\qquad\qquad\qquad\qquad\quad\qquad\;\;\;\,$ $=$ $\sum\limits_{d=1}^n$$\mu$$(d)$$\sum\limits_{i=1}^n\sum\limits_{j=1}^m$$[d|\gcd(i,j)]$ $\quad\gets$ 根据乘法分配律把 $d$ 扔到前面去,那么此时 $i$ 和 $j$ 都是 $d$ 的倍数才能 $+1$

$\qquad\qquad\qquad\qquad\qquad\qquad\quad\qquad\;\;\;\,$ $=$ $\sum\limits_{d=1}^n$$\mu$$(d)$$\lfloor$$\frac{n}{d}$$\rfloor$$\lfloor$$\frac{m}{d}$$\rfloor$ $\quad\gets$ 可以发现小于等于 $n$ 的 $d$ 的倍数一共有 $\lfloor\frac{n}{d}\rfloor$ 个,同理我们可以搞掉 $m$

$\qquad\qquad\quad\;$ 然后我们就可以用数论分块比较容易地完成了

 

$\mathit{2.}$ 求最大公约数为 $k$ 的数对个数 $\quad\sum\limits_{i=1}^n\sum\limits_{j=1}^m$$[\gcd(i,j)=k]$ $=$ $\sum\limits_{d=1}^n$$\mu$$(d)$$\lfloor$$\frac{n}{kd}$$\rfloor$$\lfloor$$\frac{m}{kd}$$\rfloor$

$\qquad$ 看上去很熟悉?没错

$\qquad$ 让 $i$ 和 $j$ 同时除以 $k$ 就是 $\sum\limits_{i=1}^{\lfloor\frac{n}{k}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{k}\rfloor}$$[\gcd(i,j)=1]$

 

$\mathit{3.}$ 求最大公约数为质数的数对个数 $\quad\sum\limits_{p=1,p\in prime}^{min(n,m)}\sum\limits_{i=1}^n\sum\limits_{j=1}^m$$[\gcd(i,j)=p]$ ( YY的GCD

$\qquad$ 就是在上一问里加一个 $\sum\limits_{p=1}^{min(n,m)}(p\in prime)$

$\qquad$ $\quad\sum\limits_{p=1,p\in prime}^{min(n,m)}\sum\limits_{i=1}^n\sum\limits_{j=1}^m$$[\gcd(i,j)=p]$ $=$ $\sum\limits_{p=1,p\in prime}^{n}\sum\limits_{d=1}^{\lfloor\frac{n}{p}\rfloor}$$\mu$$(d)$$\lfloor$$\frac{n}{pd}$$\rfloor$$\lfloor$$\frac{m}{pd}$$\rfloor$

$\qquad$ 不妨设 $T = pd$ 那么有原式 $=$ $\sum\limits_{p=1,p\in prime}^{n}\sum\limits_{d=1}^{\lfloor\frac{n}{p}\rfloor}\mu(d)\lfloor\frac{n}{T}\rfloor\lfloor\frac{m}{T}\rfloor$

$\qquad\qquad\qquad\qquad\qquad\qquad\;\;$ $=$ $\sum\limits_{T=1}^{n}\lfloor\frac{n}{T}\rfloor\lfloor\frac{m}{T}\rfloor\sum\limits_{p|T,p\in prime}\mu(\frac{T}{p})$

$\qquad$ 考虑设 $f(x) = \sum\limits_{p|x,p\in prime}\mu(\frac{x}{p})$ ,原式自然变成 $\sum\limits_{T=1}^{n}f(T)\lfloor\frac{n}{T}\rfloor\lfloor\frac{m}{T}\rfloor$

$\qquad$ 再令 $x$ 的最小质因子是 $y$,即 $x=iy$

$\qquad\qquad$ · $x \in prime$ :显然有 $f(x) = \mu(1) = 1$

$\qquad\qquad$ · $i \bmod y = 0$ 即在 $x$ 的质因数中 $y$ 出现了不止一次

$\qquad\qquad\qquad$ 当 $i$ 没有多个相同质因子,那么仅当 $p = y$ 时 $\mu(\frac{x}{p}) = \mu(i)$ 不是 $0$ ,$f(x) = \mu(i)$

$\qquad\qquad\qquad$ 当 $i$ 有多个相同质因子,那么对于任何 $p$ 都有 $\mu(\frac{x}{p}) = 0$ ,此时仍有 $\mu(\frac{x}{p})=\mu(i)$ ,因此 $f(x) = \mu(i)}

$\qquad\qquad$ · $i \bmod y \ne 0$ 即在 $x$ 的质因数中 $y$ 仅出现了一次

$\qquad\qquad\qquad$ $f(x) = \sum\limits_{p|x,p\in prime}\mu(\frac{i\times y}{p})\;$ ,$\;$$f(i) = \sum\limits_{p|i,p\in prime}\mu(\frac{i}{p})$,且 $x = i\times y$

$\qquad\qquad\qquad$ 显然的,$f(x)$ 中的每一项( $\mu(\frac{i\times y}{p})$ )都是 $f(i)$ 中的某一项( $\mu(\frac{i}{p})$ ) 的分子乘上一个 $y$ 得来

$\qquad\qquad\qquad$ 又因为 $\mu(x)$ 是积性函数,因此 $\mu(\frac{i\times y}{p})$ $=$ $\mu(\frac{i}{p})\times \mu(y)$ $=$ $-\mu(\frac{i}{p})$

$\qquad\qquad\qquad$ 然鹅发现 $f(x)$ 中还有一个质因子 $y$ ,也就是有一项 $f(i)$ 中没有的 $\mu(\frac{i\times y}{y})$ $=$ $\mu(i)$

$\qquad\qquad\qquad$ $\therefore$ $f(x) = -f(i) + \mu(i)$

$\qquad$ $\therefore$ 我们可以预处理 $f(x)$ ,这样可以在多组数据询问的情况下跑过

 

 

#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#define int long long
#define WR WinterRain
using namespace std;
const int WR=10010000;
int t,n,m;
int f[WR],sum[WR];
int prime[WR],cnt,miu[WR];
bool flag[WR];
int read(){
    int s=0,w=1;
    char ch=getchar();
    while(ch>'9'||ch<'0'){
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        s=(s<<3)+(s<<1)+ch-48;
        ch=getchar();
    }
    return s*w;
}
void Euler(){
    miu[1]=1;
    for(int i=2;i<WR;i++){
        if(!flag[i]) prime[++cnt]=i,miu[i]=-1;
        for(int j=1;j<=cnt&&i*prime[j]<WR;j++){
            flag[i*prime[j]]=true;
            if(i%prime[j]==0){
                miu[i*prime[j]]=0;
                break;
            }
            miu[i*prime[j]]=-miu[i];
        }
    }
    for(int i=1;i<=cnt;i++){
        for(int j=1;j*prime[i]<WR;j++){
            f[prime[i]*j]+=miu[j];
        }
    }
    for(int i=1;i<WR;i++) sum[i]=sum[i-1]+f[i];
}
signed main(){
    Euler();
    t=read();
    while(t--){
        int ans=0,pos=0;
        n=read(),m=read();
        for(int i=1;i<=min(n,m);i=pos+1){
            pos=min(n/(n/i),m/(m/i));
            ans+=(sum[pos]-sum[i-1])*(n/i)*(m/i);
        }
        printf("%lld\n",ans);
    }
    return 0;
}
View Code

 

$\mathit{4.}$ 求最大公约数为 $k$ 的数对个数 ( 考虑 $i$ 和 $j$ 贡献 ) $\quad\sum\limits_{i=1}^n\sum\limits_{j=1}^m$$ij[\gcd(i,j)=k]$

$\qquad$ $\quad\sum\limits_{i=1}^n\sum\limits_{j=1}^m$$ij[\gcd(i,j)=k]$ $=$ $k^2\sum\limits_{i'=1}^{\lfloor\frac{n}{k}\rfloor}\sum\limits_{j'=1}^{\lfloor\frac{m}{k}\rfloor}$$i'j'[\gcd(i',j')=1]$ $\quad\gets$ 这里我们把 $i$ 和 $j$ 都提出了一个 $k$ ,因此 $i = i'\times k$,$j = j'\times k$

$\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad\;$ $\quad$ 又因为要计算 $i$ 和 $j$ 的贡献因此不能像上一个式子一样直接忽略

$\qquad\qquad\qquad\qquad\qquad\qquad\qquad$ $=$ $k^2\sum\limits_{i=1}^{\lfloor\frac{n}{k}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{k}\rfloor}$$ij\sum\limits_{d|\gcd(i,j)}\mu(d)$ $\quad\gets$ 这里把 $\gcd(i,j)$ 化掉

$\qquad\qquad\qquad\qquad\qquad\qquad\qquad$ $=$ $k^2\sum\limits_{d=1}^{\lfloor\frac{n}{k}\rfloor}\mu(d)\sum\limits_{i=1}^{\lfloor\frac{n}{k}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{k}\rfloor}$$ij[d|\gcd(i,j)]$ $\quad\gets$ 把 $d$ 扔到前面去

$\qquad\qquad\qquad\qquad\qquad\qquad\qquad$ $=$ $k^2\sum\limits_{d=1}^{\lfloor\frac{n}{k}\rfloor}\mu(d)d^{2}\sum\limits_{i=1}^{\lfloor\frac{n}{kd}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{kd}\rfloor}$$ij$ $\quad\gets$ 这里我们像 $\mathit{1}$ 一样把后面的 $\gcd(i,j)$ 化掉,又因为要计算 $i$ 和 $j$ 的贡献乘一个 $d^2$

$\qquad\qquad\qquad\qquad\qquad\qquad\qquad$ $=$ $k^2\sum\limits_{d=1}^{\lfloor\frac{n}{k}\rfloor}\mu(d)d^{2}\sum\limits_{i=1}^{\lfloor\frac{n}{kd}\rfloor}i\sum\limits_{j=1}^{\lfloor\frac{m}{kd}\rfloor}j$

$\qquad\qquad\;$ 注意到 $\sum\limits_{i=1}^{\lfloor\frac{n}{kd}\rfloor}i\sum\limits_{j=1}^{\lfloor\frac{m}{kd}\rfloor}j$ 这两项像极了等差数列,于是我们可以设 $f(n)=\sum\limits_{i=1}^{n}=\frac{n(n+1)}{2}$

$\qquad\qquad\;$ 原式 $=$ $k^2\sum\limits_{d=1}^{\lfloor\frac{n}{k}\rfloor}\mu(d)d^{2}f(\lfloor\frac{n}{kd}\rfloor)f(\lfloor\frac{m}{kd}\rfloor)$

$\mathit{5.}$ 求 $\gcd$ 之和 $\quad\sum\limits_{i=1}^n\sum\limits_{j=1}^m$$\gcd(i,j)$

$\qquad$ :$\quad\sum\limits_{i=1}^n\sum\limits_{j=1}^m$$\gcd(i,j)$ $=$ $\sum\limits_{k=1}^{n}k\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}[\gcd(i,j)=k]$ $\quad\gets$ 这里枚举 $\gcd(i,j)$

$\qquad\qquad\qquad\qquad\qquad\quad$ $=$ $\sum\limits_{k=1}^{n}k\sum\limits_{i=1}^{\lfloor\frac{n}{k}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{k}\rfloor}$$[\gcd(i,j)=1]$

$\qquad\qquad\qquad\qquad\qquad\quad$ $=$ $\sum\limits_{k=1}^{n}k\sum\limits_{i=1}^{\lfloor\frac{n}{k}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{k}\rfloor}$$[\gcd(i,j)=1]$

$\qquad\qquad\qquad\qquad\qquad\quad$ $=$ $\sum\limits_{k=1}^{n}k\sum\limits_{i=1}^{\lfloor\frac{n}{k}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{k}\rfloor}$$\sum\limits_{d|\gcd(i,j)}\mu(d)$

$\qquad\qquad\qquad\qquad\qquad\quad$ $=$ $\sum\limits_{k=1}^{n}k\sum\limits_{d=1}^{\lfloor\frac{n}{k}\rfloor}\mu(d)\lfloor\frac{n}{kd}\rfloor\lfloor\frac{m}{kd}\rfloor$

$\qquad$ 但是还有更优秀的解法
$\qquad$ 解:根据性质 $\mathit{2}$ $\quad\sum\limits_{i=1}^n\sum\limits_{j=1}^m$$\gcd(i,j)$ $=$ $\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}\sum\limits_{d|\gcd(i,j)}φ(d)$
$\qquad\qquad\qquad\qquad\qquad\qquad\qquad\quad\;$ $=$ $\sum\limits_{d=1}^{n}φ(d)\lfloor\frac{n}{d}\rfloor\lfloor\frac{m}{d}\rfloor$ $\quad\gets$ 根据公式 $\mathit{1}$ 可得
 

$\mathit{6.}$ 求 $\operatorname{lcm}$ 之和 $\quad\sum\limits_{i=1}^n\sum\limits_{j=1}^m$$\operatorname{lcm}(i,j)$ (Crash的数字表格/JZPTAB

$\qquad$ :$\quad\sum\limits_{i=1}^n\sum\limits_{j=1}^m$$\operatorname{lcm}(i,j)$ $=$ $\sum\limits_{i=1}^n\sum\limits_{j=1}^m$$\frac{ij}{\gcd(i,j)}$
$\qquad\qquad\qquad\qquad\qquad\quad$ $=$ $\sum\limits_{k=1}^{n}\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}\frac{ij}{k}[\gcd(i,j)=k]$ $\quad\gets$ 这里像 $\mathit{4}$ 一样枚举 $k$
$\qquad\qquad\qquad\qquad\qquad\quad$ $=$ $\sum\limits_{k=1}^{n}\sum\limits_{i=1}^{\lfloor\frac{n}{k}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{k}\rfloor}\frac{(i\times k)(j\times k)}{k}[\gcd(i,j)=1]$
$\qquad\qquad\qquad\qquad\qquad\quad$ $=$ $\sum\limits_{k=1}^{n}k\sum\limits_{i=1}^{\lfloor\frac{n}{k}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{k}\rfloor}ij[\gcd(i,j)=1]$
$\qquad\qquad\qquad\qquad\qquad\quad$ $=$ $\sum\limits_{k=1}^{n}k\sum\limits_{i=1}^{\lfloor\frac{n}{k}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{k}\rfloor}ij\sum\limits_{d|\gcd(i,j)}\mu(d)$ $\quad\gets$ 换成 $\mu(d)$
$\qquad\qquad\qquad\qquad\qquad\quad$ $=$ $\sum\limits_{k=1}^{n}k\sum\limits_{d=1}^{n}\mu(d)(\sum\limits_{i=1}^{\lfloor\frac{n}{k}\rfloor}i[d|i])(\sum\limits_{j=1}^{\lfloor\frac{m}{k}\rfloor}j[d|j])$
$\qquad\qquad\qquad\qquad\qquad\quad$ $=$ $\sum\limits_{k=1}^{n}k\sum\limits_{d=1}^{n}\mu(d)(d\sum\limits_{i=1}^{\lfloor\frac{n}{kd}\rfloor}i)(d\sum\limits_{j=1}^{\lfloor\frac{m}{kd}\rfloor}j)$ $\quad\gets$ 提出 $d$
$\qquad\qquad\qquad\qquad\qquad\quad$ $=$ $\sum\limits_{k=1}^{n}k\sum\limits_{d=1}^{n}d^{2}\mu(d)\sum\limits_{i=1}^{\lfloor\frac{n}{kd}\rfloor}i\sum\limits_{j=1}^{\lfloor\frac{m}{kd}\rfloor}j$ 
 
$\qquad\qquad\quad$ 我们还是可以设 $f(i) = \frac{i(i+1)}{2}$,于是就可以暂时把它优化到 $\sum\limits_{k=1}^{n}k\sum\limits_{d=1}^{n}d^{2}\mu(d)f(\lfloor\frac{n}{kd}\rfloor)f(\lfloor\frac{m}{kd}\rfloor)$ ,这是一个 $O(n)$ 算法
$\qquad\qquad\quad$ 但是如果有 $M$ 组询问我们需要一个 $O(M\sqrt{n})$ 的算法
$\qquad\qquad\quad$ 我们设 $T = kd$ ,可以发现前面那一堆 $\sum\limits_{k=1}^{n}k\sum\limits_{d=1}^{n}d^{2}\mu(d)$ $=$ $\sum\limits_{d=1}^{n}d^{2}\mu(d)\sum\limits_{k=1}^{n}k$
$\qquad\qquad\quad$ 因为我们枚举了 $T$ 也就相当于 $k = \frac{T}{d}$ ,所以原式 $=$ $\sum\limits_{d=1}^{n}d^{2}p$ $=$ $T\sum\limits_{d=1}^{n}d$
$\qquad\qquad\quad$ 但是可以发现 $d$ 必须满足 $d|T$ 否则 $k$ 将不是整数,我们可以把后面的式子进一步化成 $T\sum\limits_{d|T}d$
$\qquad\qquad\quad$ $\therefore$ $\sum\limits_{k=1}^{n}k\sum\limits_{d=1}^{n}d^{2}\mu(d)f(\lfloor\frac{n}{kd}\rfloor)f(\lfloor\frac{m}{kd}\rfloor)$ $=$ $\sum\limits_{T=1}^{n}Tf(\lfloor\frac{n}{kd}\rfloor)f(\lfloor\frac{m}{kd}\rfloor)\sum\limits_{d|T}d\mu(d)$
$\qquad\qquad\quad$ 观察可得只有 $g(T) = \sum\limits_{d|T}d\mu(d)$ 这一块是有难度的,考虑狄利克雷卷积
$\qquad\qquad\quad$ 设 $T = \prod\limits_{i=1}^k p_{i}^{\alpha_{i}}  ( p_{i} 为互异素数) $ ,显然 $g(T)$ 是一个积性函数,可以把它卷成 $g(T) = \prod\limits_{i=1}^{k}g(p_{i}^{\alpha_{i}}) = \prod\limits_{i=1}^{k}(1-p_{i})$ 
$\qquad\qquad\quad$ $\therefore$ $\quad\sum\limits_{i=1}^n\sum\limits_{j=1}^m$$\operatorname{lcm}(i,j)$ $=$ $\sum\limits_{T=1}^{n}Tg(T)f(\lfloor\frac{n}{kd}\rfloor)f(\lfloor\frac{m}{kd}\rfloor)$
$\qquad\qquad\quad$ 可以预处理 $T\times g(T)$ 前缀和,在线性筛内完成
 
#include<cstdio>
#include<cstring>
#include<string>
#define int long long
#define WR WinterRain
using namespace std;
const int WR=10010000,mod=100000009;
int n,m,ans;
int f[WR];
int prime[WR],cnt,miu[WR];
bool flag[WR];
int read(){
    int s=0,w=1;
    char ch=getchar();
    while(ch>'9'||ch<'0'){
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        s=(s<<3)+(s<<1)+ch-48;
        ch=getchar();
    }
    return s*w;
}
void Euler(){
    miu[1]=1,f[1]=1;
    for(int i=2;i<WR;i++){
        if(!flag[i]) prime[++cnt]=i,miu[i]=-1,f[i]=-i+1+mod;
        for(int j=1;i*prime[j]<WR&&j<=cnt;j++){
            flag[i*prime[j]]=true;
            if(i%prime[j]==0){
                miu[i*prime[j]]=0;
                f[i*prime[j]]=f[i];
                break;
            }
            miu[i*prime[j]]=-miu[i];
            f[i*prime[j]]=(f[i]*f[prime[j]])%mod;
        }
    }
    for(int i=1;i<WR;i++) f[i]=f[i]*i%mod;
    for(int i=1;i<WR;i++) f[i]=(f[i]+f[i-1])%mod;
}
signed main(){
    Euler();
    int t=read();
    while(t--){
        ans=0;
        n=read(),m=read();
        int j=0;
        for(int i=1;i<=min(n,m);i=j+1){
            j=min(m/(m/i),n/(n/i));
            ans=(ans+((n/i)*(n/i+1)/2%mod)*((m/i)*(m/i+1)/2%mod)%mod*(f[j]-f[i-1]+mod)%mod)%mod;
        }
        printf("%lld\n",(ans+mod)%mod);
    }
    return 0;
}
View Code

 

$\mathit{7.}$ 求 $\gcd$ 的幂次方之和 $\quad\sum\limits_{i=1}^n\sum\limits_{j=1}^m$$\gcd(i,j)^k$ (于神之怒加强版

$\qquad$ $\quad\sum\limits_{i=1}^n\sum\limits_{j=1}^m$$\gcd(i,j)^k$ $=$ $\sum\limits_{p=1}^{n}p^k\sum\limits_{i=1}^n\sum\limits_{j=1}^m[\gcd(i,j)=p]$

$\qquad\qquad\qquad\qquad\qquad\quad\;$ $=$ $\sum\limits_{p=1}^{n}p^k\sum\limits_{i=1}^{\lfloor\frac{n}{p}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{p}\rfloor}[\gcd(i,j)=1]$

$\qquad\qquad\qquad\qquad\qquad\quad\;$ $=$ $\sum\limits_{p=1}^{n}p^k\sum\limits_{i=1}^{\lfloor\frac{n}{p}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{p}\rfloor}\sum\limits_{d|\gcd(i,j)}\mu(d)$

$\qquad\qquad\qquad\qquad\qquad\quad\;$ $=$ $\sum\limits_{p=1}^{n}p^k\sum\limits_{d=1}^{\lfloor\frac{n}{p}\rfloor}\mu(d)\sum\limits_{i=1}^{\lfloor\frac{n}{p}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{p}\rfloor}[d|i][d|j]$

$\qquad\qquad\qquad\qquad\qquad\quad\;$ $=$ $\sum\limits_{p=1}^{n}p^k\sum\limits_{d=1}^{\lfloor\frac{n}{p}\rfloor}\mu(d)\lfloor\frac{n}{pd}\rfloor\lfloor\frac{m}{pd}\rfloor$

$\qquad\qquad$ 不妨设 $T = pd$ ,那么原式 $=$ $\sum\limits_{p=1}^{n}p^k\sum\limits_{d=1}^{\lfloor\frac{n}{p}\rfloor}\mu(d)\lfloor\frac{n}{T}\rfloor\lfloor\frac{m}{T}\rfloor$

$\qquad\qquad\qquad\qquad\qquad\qquad\;\;$ $=$ $\sum\limits_{T=1}^{n}\lfloor\frac{n}{T}\rfloor\lfloor\frac{m}{T}\rfloor\sum\limits_{p|T}^{n}p^k\sum\limits_{d=1}^{\lfloor\frac{n}{p}\rfloor}\mu(d)$

$\qquad\qquad\qquad\qquad\qquad\qquad\;\;$ $=$ $\sum\limits_{T=1}^{n}\lfloor\frac{n}{T}\rfloor\lfloor\frac{m}{T}\rfloor\sum\limits_{p|T}^{n}p^k\mu(\frac{T}{p})$

$\qquad\qquad$ 设 $f(x)$ $=$ $\sum\limits_{p|x}^{n}p^k\mu(\frac{x}{p})$ ,那么显然的 $f(x)$ 是一个积性函数

$\qquad\qquad$ $\because$ $T = \prod\limits_{i=1}^{num} p_{i}^{\alpha_i}$ $\qquad$ $\therefore$ $f(T) = \prod\limits_{i=1}^{num} f(p_{i}^{\alpha_i})$

$\qquad\qquad$ 可以发现 $f(p^{\alpha}) = p^{\alpha k} - p^{(\alpha-1)k}$ ,因此 $f(T) = \prod\limits_{i=1}^{num}(p_i^{\alpha_i k}-p_i^{\alpha_{i-1} k})$

$\qquad\qquad$ 设 $p_t \in prime$ ,那么 $\frac{f(ap_t)}{f(a)}$ $=$ $\frac{\prod\limits_{i=1}^{num}f(p_i^{\alpha_i + [i=t]})}{\prod\limits_{i=1}^{num}f(p_i^{\alpha_i})}$ $=$ $\frac{f(p_t^{\alpha_t + 1})}{f(p_t^{\alpha_t})}$ $=$ $p_t^k$

$\qquad\qquad$ $\therefore\quad$ $\gcd(a,p_t) > 1$ 时 $f(ap_t) = p_t^kf(a)$ ,同时当 $\gcd(a,p_t) = 1$ 时 $f(ap_t) = f(a)f(p_t)$

 

 

#include<cstdio>
#include<cstring>
#include<string>
#define int long long
#define WR WinterRain
using namespace std;
const int WR=10010000,mod=1e9+7;
int t;
int n,m,k,ans;
int pw[WR],f[WR];
int prime[WR],cnt,miu[WR];
bool flag[WR];
int read(){
    int s=0,w=1;
    char ch=getchar();
    while(ch>'9'||ch<'0'){
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        s=(s<<3)+(s<<1)+ch-48;
        ch=getchar();
    }
    return s*w;
}
int quick_pow(int a,int b){
    int base=a,ans=1;
    while(b){
        if(b&1) ans=ans*base%mod;
        base=base*base%mod;
        b>>=1;
    }
    return ans;
}
void Euler(){
    miu[1]=1,f[1]=1;
    for(int i=2;i<WR;i++){
        if(!flag[i]){
            prime[++cnt]=i,miu[i]=-1;
            pw[cnt]=quick_pow(i,k),f[i]=(pw[cnt]-1+mod)%mod;
        }
        for(int j=1;i*prime[j]<WR&&j<=cnt;j++){
            flag[i*prime[j]]=true;
            if(i%prime[j]==0){
                miu[i*prime[j]]=0;
                f[i*prime[j]]=f[i]*pw[j]%mod;
                break;
            }
            miu[i*prime[j]]=-miu[i];
            f[i*prime[j]]=(f[i]*f[prime[j]])%mod;
        }
    }
    for(int i=1;i<WR;i++) f[i]=(+f[i]+f[i-1])%mod;
}
signed main(){
    t=read(),k=read();
    Euler();
    while(t--){
        n=read(),m=read();
        int pos,ans=0;
        for(int i=1;i<=min(n,m);i=pos+1){
            pos=min(n/(n/i),m/(m/i));
            ans=(ans+(f[pos]-f[i-1]+mod)%mod*(n/i)%mod*(m/i)%mod)%mod;
        }
        printf("%lld\n",ans);
    }
    return 0;
}
View Code

 

$\mathit{8.}$ 约数个数和 $\quad\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}d(ij)$ 其中 $d(i)$ 表示 $i$ 的约数个数

$\qquad$ :首先证明 $d(ij) = \sum\limits_{x|i}\sum\limits_{y|j}[\gcd(x,y)=1]$

$\qquad\quad\;\;\,$ 考虑某一个质因子 $p$

$\qquad\quad\;\;\,$ 若 $i$ 包含 $\lambda$ 个 $p$ ,$j$ 包含 $\mu$ 个 $p$ ,那么显然的 $i\times j$ 包含 $\lambda + \mu$ 个 $p$ ,此时等式左边有 $\lambda + \mu + 1$ 种对 $p$ 的选法

$\qquad\quad\;\;\,$ 同理 $x$ 可以包含 $[0,\lambda ]$ 个 $p$ ,$y$ 可以包含 $[0,\mu ]$个 $p$ ,我们有 $\lambda + \mu + 1$ 种情况满足 $\gcd(x,y) = 1$

$\qquad\quad\;\;\,$ $\quad$ · $\,$$x = 0$ ,$y = 0$ ,贡献是 $1$

$\qquad\quad\;\;\,$ $\quad$ · $\,$$x = 0$ ,$y \in [1,\mu]$ ,贡献是 $\mu$

$\qquad\quad\;\;\,$ $\quad$ · $\,$$x \in [1,\lambda]$ ,$y = 0$ ,贡献是 $\lambda$

$\qquad\quad\;\;\,$ 三者相加就是 $\lambda + \mu + 1$ ,可以得证

$\qquad\quad\;\;\,$ $\therefore$ 原式 $= \sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}\sum\limits_{x|i}\sum\limits_{y|j}[\gcd(x,y) = 1]$

$\qquad\qquad\qquad\;\;$ $=$ $\sum\limits_{x=1}^{n}\sum\limits_{y=1}^{m}\lfloor\frac{n}{x}\rfloor\lfloor\frac{m}{y}\rfloor[\gcd(x,y)=1]$ $\quad\gets$ $[1,n]$ 中 $x$ 的倍数有 $\lfloor\frac{n}{x}\rfloor$ 个,$[1,m]$ 中 $y$ 的倍数有 $\lfloor\frac{m}{y}\rfloor$ 个,可以消掉两个 $\sum$

$\qquad\qquad\qquad\;\;$ $=$ $\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}\lfloor\frac{n}{i}\rfloor\lfloor\frac{m}{j}\rfloor[\gcd(i,j)=1]$

$\qquad\qquad\qquad\;\;$ $=$ $\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}\lfloor\frac{n}{i}\rfloor\lfloor\frac{m}{j}\rfloor\sum\limits_{d|\gcd(i,j)}\mu(d)$

$\qquad\qquad\qquad\;\;$ $=$ $\sum\limits_{d=1}^{\min(n,m)}\mu(d)\sum\limits_{i=1}^{\frac{n}{d}}\lfloor\frac{n}{di}\rfloor\sum\limits_{j=1}^{\frac{m}{d}}\lfloor\frac{m}{dj}\rfloor$

$\qquad\quad\;\;\,$ 不妨设 $f(x) = \sum\limits_{i=1}^{x}\lfloor\frac{x}{i}\rfloor$ 

$\qquad\quad\;\;\,$ 那么显然的原式 $= \sum\limits_{d=1}^{\min(n,m)}\mu(d)f(\frac{n}{d})f(\frac{m}{d})$

$\qquad\quad\;\;\,$ 可以 $O(n\sqrt{n})$ 预处理 $f(x)$ ,用 $O(\sqrt{n})$ 查询

 

 

#include<cstdio>
#include<cstring>
#include<string>
#define int long long
#define WR WinterRain
using namespace std;
const int WR=100100,mod=1e9+7;
int t;
int n,m,k;
int f[WR],g[WR];
int table[2010][2010];
int prime[WR],cnt,miu[WR];
bool flag[WR];
int read(){
    int s=0,w=1;
    char ch=getchar();
    while(ch>'9'||ch<'0'){
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        s=(s<<3)+(s<<1)+ch-48;
        ch=getchar();
    }
    return s*w;
}
int quick_pow(int a,int b){
    int base=a,ans=1;
    while(b){
        if(b&1) ans=ans*base%mod;
        base=base*base%mod;
        b>>=1;
    }
    return ans;
}
void Euler(){
    miu[1]=1,g[1]=1,f[1]=1;
    for(int i=2;i<WR;i++){
        if(!flag[i]){
            prime[++cnt]=i;
            miu[i]=-1;
            f[i]=1,g[i]=2;
        }
        for(int j=1;i*prime[j]<WR&&j<=cnt;j++){
            flag[i*prime[j]]=true;
            if(i%prime[j]==0){
                g[i*prime[j]]=g[i]/(f[i]+1)*(f[i]+2);
                f[i*prime[j]]=f[i]+1;
                miu[i*prime[j]]=0;
                break;
            }
            miu[i*prime[j]]=-miu[i];
            g[i*prime[j]]=g[i]*g[prime[j]];
            f[i*prime[j]]=1;
        }
    }
    for(int i=2;i<WR;i++) miu[i]+=miu[i-1];
    for(int i=2;i<WR;i++) g[i]+=g[i-1];
}
signed main(){
    Euler();
    t=read();
    while(t--){
        n=read(),m=read();
        if(n<=2000&&m<=2000){
            if(table[n][m]){
                printf("%lld\n",table[n][m]);
                continue;
            }
        }
        int pos,ans=0;
        for(int i=1;i<=min(n,m);i=pos+1){
            pos=min(n/(n/i),m/(m/i));
            ans+=(miu[pos]-miu[i-1])*g[n/i]*g[m/i];
        }
        if(n<=2000&&m<=2000) table[n][m]=table[m][n]=ans;
        printf("%lld\n",ans);
    }
    return 0;
}
View Code

 

$\mathit{9.}$ 求 $\gcd$ 的约数和之和 $\quad\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}\sigma_{1}(\gcd(i,j))$(数表

$\qquad$ 这里的 $\sigma_{1}(x)$ 函数指 $x$ 的约数和

$\qquad$ 那么显然地,我们可以把上面的式子化成 $\sum\limits_{T=1}^{n}\lfloor\frac{n}{T}\rfloor\lfloor\frac{m}{T}\rfloor\sum\limits_{d|T}\sigma_{1}(d)\mu(\frac{T}{d})$

$\qquad$ 考虑将询问按 $a$ 从小到大排序,枚举询问的时候,$a$ 变大会使得一些 $\sigma_1(d)$ 对 $g(T)$ 产生贡献,我们就用枚举倍数的方法来找到所有的 $T$

$\qquad$ 然后我们需要动态修改 $g(T)$ 的值,支持区间询问,因此可以使用树状数组实现

 

#include<cstring>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define int long long
#define WR WinterRain
using namespace std;
const int WR=1001000;
struct Node{
    int n,m,a,id;
    bool operator<(const Node &b)const{
        return a<b.a;
    }
}ask[WR<<1];
int tree[WR<<1];
int f[WR<<1];
int prime[WR<<1],cnt,mu[WR<<1];
bool isprime[WR<<1];
pair<int,int>g[WR<<1];
int read(){
    int s=0,w=1;
    char ch=getchar();
    while(ch>'9'||ch<'0'){
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        s=(s<<1)+(s<<3)+ch-48;
        ch=getchar();
    }
    return s*w;
}
int lowbit(int x){
    return x&(-x);
}
void modify(int k,int val){
    for(int i=k;i<WR;i+=lowbit(i)){
        tree[i]+=val;
    }
}
int query(int k){
    int res=0;
    for(int i=k;i;i-=lowbit(i)){
        res+=tree[i];
    }
    return res;
}
void sieve(){
    mu[1]=1;
    g[1]=make_pair(1,1);
    for(int i=2;i<WR;i++){
        if(!isprime[i]){
            prime[++cnt]=i;
            mu[i]=-1;f[i]=i+1;g[i]=make_pair(i+1,i);
        }
        for(int j=1;j<=cnt&&i*prime[j]<WR;j++){
            isprime[i*prime[j]]=true;
            if(i%prime[j]==0){
                mu[i*prime[j]]=0;
                f[i*prime[j]]=f[i]*prime[j]+1;
                g[i*prime[j]]=make_pair((int)g[i].first/f[i]*f[i*prime[j]],i*prime[j]);
                break;
            }
            mu[i*prime[j]]=-mu[i];
            f[i*prime[j]]=prime[j]+1;
            g[i*prime[j]]=make_pair(g[i].first*g[prime[j]].first,i*prime[j]);
        }
    }
}
int solve(int n,int m){
    int res=0;
    if(n>m) swap(n,m);
    for(int i=1,j;i<=n;i=j+1){
        j=min(n/(n/i),m/(m/i));
        // printf("%lld\n",j);
        res=res+(query(j)-query(i-1))*(int)(n/i)*(int)(m/i);
    }
    return res;
}
int ans[WR];
signed main(){
    sieve();
    sort(g+1,g+WR);
    // for(int i=1;i<=100;i++) printf("%lld %lld\n",g[i].first,g[i].second);
    int q=read();
    for(int i=1;i<=q;i++){
        ask[i].n=read(),ask[i].m=read(),ask[i].a=read(),ask[i].id=i;
    }
    sort(ask+1,ask+1+q);
    for(int i=1,j=1;i<=q;i++){
        while(g[j].first<=ask[i].a&&j<WR){
            for(int k=g[j].second;k<WR;k+=g[j].second){
                modify(k,g[j].first*mu[(int)k/g[j].second]);
            }
            j++;
        }
        ans[ask[i].id]=solve(ask[i].m,ask[i].n);
    }
    int mod=(1<<31);
    for(int i=1;i<=q;i++){
        printf("%lld\n",ans[i]%mod);
    }
    return 0;
}
View Code

 

$\mathit{10.}$ 求 $\gcd$ 所含质因子的最大幂指数之和  $\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}f(\gcd(i,j))$ 

$\qquad$ 依旧显然地,我们可以把上面的式子化成 $\sum\limits_{T=1}^{n}\lfloor\frac{n}{T}\rfloor\lfloor\frac{m}{T}\rfloor\sum\limits_{d|T}f(d)\mu(\frac{T}{d})$

$\qquad$ 不妨设 $h(T)=\sum\limits_{d|T}f(d)\mu(\frac{T}{d})$ ,我们假设 $T$ 被唯一分解为 $p_1^{\alpha_1}p_2^{\alpha_2}\cdots p_k^{\alpha_k}$

$\qquad$ 为了保证有贡献我们要让 $\mu(\frac{T}{d})$ 非零,那么 $\frac{T}{d}$ 的最大指数幂不能超过一

$\qquad$ 也就是说枚举的$d=p_1^{\beta_1}p_2^{\beta_2}\cdots p_k^{\beta_k}$ 必须满足,对于所有 $i\in [1,k]$ 有 $0\leqslant a_i−b_i \leqslant 1$

$\qquad$ 那么这么来说对于每个 $T$ ,设其一共含有 $k$ 种不同的质因数,那么会给它贡献的就只有 $2^k$ 个数。枚举的每个 $d$,就有 $f(d)=\max\{\beta_i\}$

$\qquad$ 分两种情况讨论:

$\qquad$ 1、存在一组 $i,j$ 使 $\alpha_i<\alpha_j$

$\qquad\qquad$ 那么此时 $\beta_i$ 就永远不可能成为 $\max\{\beta_i\}$ ,换言之,无论你取不取这个 $i$ ,$f(d)$ 的值算出来都是一样的。

$\qquad\qquad$ 又因为取这个 $i$ 的时候的 $\mu(Td)$ 值与不取这个 $i$ 的时候的 $\mu(Td)$ 值恰好相反,所以加起来就会有 $h(T)=0$。

$\qquad$ 2、所有 $\alpha_i$ 都相等

$\qquad\qquad$ 还是装作上一种情况算,不同之处在于当所有 $\beta_i$ 取 $\alpha_i−1$ 的时候$f(d)=\beta_i=\alpha_i−1$

$\qquad\qquad$ 那么这时 $h(T)$ 的值就只与这个 $-1$ 前面的 $\mu$ 值有关(因为其他的都抵消掉了)。

$\qquad\qquad$ 易知这个 $-1$ 前面的系数是 $\mu(p_1p_2\cdots p_k)$,所以说 $h(T)=−(−1)^k=(−1)^{k+1}$

$\qquad$ 线性筛记录每个数的最小质因子的幂指数和最小质因子的指数次幂,判除掉最小质因子后最小质因子的幂指数是否相等

 

 

#include<cstring>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define int long long
#define WR WinterRain
using namespace std;
const int WR=10001000;
int a[WR],h[WR],low[WR],mu[WR];
int prime[WR>>1],cnt;
bool isprime[WR];
int read(){
    int s=0,w=1;
    char ch=getchar();
    while(ch>'9'||ch<'0'){
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        s=(s<<1)+(s<<3)+ch-48;
        ch=getchar();
    }
    return s*w;
}
void sieve(){
    mu[1]=1;
    for(int i=2;i<WR;i++){
        if(!isprime[i]){
            low[i]=prime[++cnt]=i;
            mu[i]=-1;
            a[i]=h[i]=1;
        }
        for(int j=1;j<=cnt&&i*prime[j]<WR;j++){
            isprime[i*prime[j]]=true;
            if(i%prime[j]==0){
                a[i*prime[j]]=a[i]+1;
                low[i*prime[j]]=low[i]*low[prime[j]];
                if(i==low[i]) h[i*prime[j]]=1;
                else h[i*prime[j]]=(a[i/low[i]]==a[i*prime[j]]?-h[i/low[i]]:0);
                break;
            }
            a[i*prime[j]]=1;
            low[i*prime[j]]=prime[j];
            h[i*prime[j]]=(a[i]==1)?-h[i]:0;
        }
    }
    for(int i=1;i<WR;i++) h[i]+=h[i-1];
}
signed main(){
    sieve();
    int t=read();
    while(t--){
        int n=read(),m=read();
        if(n>m) swap(n,m);
        int ans=0;
        for(int i=1,j=1;i<=n;i=j+1){
            j=min(n/(n/i),m/(m/i));
            ans+=(n/i)*(m/i)*(h[j]-h[i-1]);
        }
        printf("%lld\n",ans);
    }
    return 0;
}
View Code

 

 

 

posted @ 2022-08-21 20:17  冬天丶的雨  阅读(143)  评论(4编辑  收藏  举报
Live2D