ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

莫比乌斯反演与数论分块

2021-12-11 09:00:06  阅读:174  来源: 互联网

标签:lfloor frac limits 分块 sum rfloor 反演 莫比 left


数学反演总结

1 数论分块

1.1 定理

定理 1.1.1

\[\left\lfloor\frac {\left\lfloor \frac{x}{b} \right\rfloor}{c} \right\rfloor=\left\lfloor\frac{x}{bc}\right\rfloor \]

其中 \(x\in\R,b,c\in\N\)

  • 证明:设 \(x=kbc+r\),其中 \(r\in[0,bc)\) ,我们把 \(x\) 带入左边式子可以的得到:

    \[k+\left\lfloor\frac {\left\lfloor \frac{r}{b} \right\rfloor}{c} \right\rfloor \]

    因为:

    \[0\le \left\lfloor\frac {\left\lfloor \frac{r}{b} \right\rfloor}{c} \right\rfloor\le \left\lfloor\frac {r}{bc} \right\rfloor=0 \]

    所以我们可以得到:

    \[\left\lfloor\frac {\left\lfloor \frac{r}{b} \right\rfloor}{c} \right\rfloor=k \]

    显然,右边式子也等于 \(k\),所以结论成立。

1.2 算法讲解

其实数论分块(又被称为除法分块)是可以在 \(\sqrt n\) 的复杂度内算出:

\[\sum\limits_{i=1}^n\lfloor \frac{n}i \rfloor \]

这是因为我们注意到和式求和的部分的取值只有 \(2\sqrt n\) 中,证明这个结论只需要讨论 \(i\le \sqrt n\) 和 \(i> \sqrt n\)​ 两种情况即可。

一般的,对于:

\[\sum\limits_{i=1}^n\lfloor \frac{n}{f(i)}\rfloor \]

我们要求其值相等的左右边界,只需要让:

\[\lfloor\frac{n}{f(l)}\rfloor=\lfloor\frac{n}{f(r)}\rfloor \]

由数论分块的正确性可以得到:

\[f(r)=\left\lfloor \frac{n}{\lfloor \frac{n}{f(l)}\rfloor}\right\rfloor \]

我们求解 \(f(l)\) 并解方程解出 \(r\) 为多少即可得出数论分块区间。

1.3 例题

1.3.1 P2261 [CQOI2007]余数求和

我们直接推式子:

\[\sum\limits_{i=1}^nk\bmod i=\sum\limits_{i=1}^nk-\lfloor \frac ki\rfloor\times i=nk-\sum\limits_{i=1}^ni\lfloor\frac ik\rfloor \]

可以应用数论分块,注意后面要特判是否等于 \(0\)。

代码:

#include<bits/stdc++.h>
#define dd double
#define ld long double
#define ll long long
#define uint unsigned int
#define ull unsigned long long
#define N number
#define M number
using namespace std;

const int INF=0x3f3f3f3f;

template<typename T> inline void read(T &x) {
    x=0; int f=1;
    char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c == '-') f=-f;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    x*=f;
}

inline ll calc(int l,int r){
    return 1ll*(r+l)*(r-l+1)/2;
}

ll ans=0,n,k;

int main(){
    read(n);read(k);
    for(int i=1;i<=n;){
        int j;
        if(k/i>0) j=k/(k/i);
        else j=n;
        j=min((ll)j,n);
        ans+=(k/i)*calc(i,j);
        i=j+1;
    }
    printf("%lld\n",n*k-ans);
    return 0;
}

代码第 \(31\) 行 \(32\) 行为特判。

1.3.2 CF1485C Floor and Mod

推式子:

\[\left\lfloor \frac{a}{b} \right\rfloor=a\bmod b=a-\lfloor\frac{a}{b}\rfloor\times b\\ \Rightarrow \lfloor\frac{a}{b}\rfloor\times (b+1) =a\Rightarrow \lfloor\frac{a}{b}\rfloor=\frac{a}{b+1} \]

所以我们只需要枚举 \(b\) ,同时统计有多少 \(a\) 是 \(b+1\) 的倍数,这个数应该是 \(\frac{x}{b+1}\) 。

但是需要注意的一点是,我们需要保证 \(\lfloor\frac{a}{b}\rfloor=\frac{a}{b+1}<b\) ,所以我们有 \(a<b^2+b\) ,所以上面这个式子应该变成:\(\frac{\min(x,b^2+b-1)}{b+1}\)。

我们根号分治并分开讨论,数论分块即可。复杂度为 \(O(\sqrt n)\)。

代码:

#include<bits/stdc++.h>
#define dd double
#define ld long double
#define ll long long
#define int long long
#define uint unsigned int
#define ull unsigned long long
#define N number
#define M number
using namespace std;

const int INF=0x3f3f3f3f;

template<typename T> inline void read(T &x) {
    x=0; int f=1;
    char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c == '-') f=-f;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    x*=f;
}

int t;
ll x,y;

inline ll calc(ll x,ll y){
    ll ans=0;ll b=1;
    for(;b*b+b-1<=x&&b<=y;b++) ans+=(b*b+b-1)/(b+1);
    for(int i=b;i<=y;){
        int j=(x/(i+1)==0)?y:(x/(x/(i+1))-1);
        j=min((ll)j,y);
        ans+=(x/(i+1))*(j-i+1);
        i=j+1;
    }
    return ans;
}

signed main(){
    // freopen("my.in","r",stdin);
    // freopen("my.out","w",stdout);
    read(t);
    while(t--){
        read(x);read(y);
        printf("%lld\n",calc(x,y));
    }
    return 0;
}

2 莫比乌斯反演(进阶版)

以前博主整理过一篇莫比乌斯反演,讲的比较基础,这里补充一下那篇博客里没有的内容。

2.1 常用公式

2.1.1 最大公因数,最小公倍数

\[\sum\limits_{i=1}^n\sum\limits_{j=1}^m\text{lcm}(i,j)=\sum\limits_{i=1}^n\sum\limits_{j=1}^m\frac{ij}{\gcd(i,j)} \\ =\sum\limits_{i=1}^n\sum\limits_{j=1}^m\sum\limits_{d|i,d|j} [\gcd(\frac id,\frac jd)=1]\frac{ij}d\\ =\sum\limits_{d=1}^{\min(n,m)}d\sum\limits_{i=1}^{\left\lfloor \frac{n}{d} \right\rfloor}\sum\limits_{j=1}^{\left\lfloor \frac{m}{d} \right\rfloor}[\gcd(i,j)=1]ij\\ \]

令 \(f(n,m)=\sum\limits_{i=1}^n\sum\limits_{j=1}^m[\gcd(i,j)=1]ij\),那么有:

\[f(n,m)=\sum\limits_{i=1}^n\sum\limits_{i=1}^m\epsilon(\gcd(i,j))ij\\ =\sum\limits_{i=1}^n\sum\limits_{j=1}^m\sum\limits_{d|\gcd(i,j)}\mu(d)ij\\ =\sum\limits_{d=1}^{\min(n,m)}\mu(d)d^2\sum\limits_{i=1}^{\left\lfloor \frac{n}{d} \right\rfloor}\sum\limits_{j=1}^{\left\lfloor \frac{m}{d} \right\rfloor}ij\\ \]

令 \(g(n,m)=\sum\limits_{i=1}^n\sum\limits_{j=1}^m ij\),显然,我们有 \(g(n,m)=\frac{(n+1)n}{2}\frac{(m+1)m}{2}\) ,可以 \(O(1)\) 计算,所以通过处理前缀和,\(f(n,m)\) 可以在 \(O(\sqrt n+\sqrt m)\) 的时间1复杂度算出,所以原式的复杂度可以做到 \(O(n+m+\sqrt n+\sqrt m)\) 。

2.1.2 除数函数

公式 2.1.2.1
  • \(\sigma_k(n)=\sum\limits_{d|n}d^k\)​​ ,令 \(id_k(n)=n^k\)​​ ,那么我们有 \(\sigma_k=id_k*I\)​​
公式2.1.2.2
  • \(\sigma_0(xy)=\sum\limits_{i|x}\sum\limits_{j|y}[\gcd(i,j)=1]\)

    证明:我们考虑将 \(xy\)​​ 的每一个因子都与互质的 \(i,j\)​​ 意义映射。设 \(xy\)​​ 的因子为 \(k\)​​ ,设把 \(k\)​​ 唯一分解之后得到的式子为 \(\prod\limits_{i=1}^mp_i^{\alpha_i}\)​​​ 我们考虑每一个质数,设当前的质数为 \(p\)​​ ,设这个质数在 \(k\)​​ 中的指数为 \(\alpha\)​​ ,设在 \(x\)​​ 中的指数为 \(a\)​​ 设在 \(y\)​​ 中的指数为 \(b\)​​​ 。我们规定,如果 \(\alpha \le a\)​ ,那么令从 \(x\)​ 中拿取 \(p^{\alpha}\)​ ,否则就从 \(y\)​ 中拿取 \(p^{\alpha -a}\)​ 次方。这样,从 \(x\)​​ 中拿出来数就与从 \(y\)​​ 中拿出来的数互质。同时每一对互质的数,都可以映射到这么一个因子上。所以等式成立。证毕。这是一个重要的式子。

定理 2.1.2.1
  • 除数函数是积性函数。

    证明:如果 \(x,y\) 互质,那么 \(xy\) 的一个因子 \(k\) ,\(k\) 一定可以分解成两个数,这两个数互质。也就是说,\(k\) 一部分来自 \(x\) ,一部分来自 \(y\)​ 。证毕。

    上面这个积性函数的性质,揭示我们除数函数也是可以线性筛的。不过我们有计算一些特殊除数函数前缀和更快的做法。

公式 2.1.2.3
  • \(\sum\limits_{i=1}^n\sigma_0(i)=\sum\limits_{j=1}^n\left\lfloor \frac{n}{j} \right\rfloor\)​

    证明:

    \[\sum\limits_{i=1}^n\sigma_0(i)=\sum\limits_{i=1}^n\sum\limits_{j=1}^i[j|i]=\sum\limits_{j=1}^n\sum\limits_{i=1}^{\left\lfloor \frac{n}{j} \right\rfloor}1=\sum\limits_{j=1}^n \left\lfloor \frac{n}{j} \right\rfloor \]

    整除分块即可。

公式 2.1.2.4
  • \(\sum\limits_{i=1}^n\sum\limits_{j=1}^m\sigma_0(ij)=\sum\limits_{d=1}^{\min(n,m)}\mu(d)(\sum\limits_{x=1}^{\left\lfloor \frac{n}{d} \right\rfloor}\left\lfloor \frac{n}{xd} \right\rfloor)(\sum\limits_{y=1}^{\left\lfloor \frac{m}{d} \right\rfloor}\left\lfloor \frac{m}{yd} \right\rfloor)\)​

    证明:

    \[\sum\limits_{i=1}^n\sum\limits_{j=1}^m\sigma_0(ij)=\sum\limits_{i=1}^n\sum\limits_{j=1}^m\sum\limits_{x|i}\sum\limits_{y|j}\epsilon(\gcd(x,y))\\ =\sum\limits_{x=1}^n\sum\limits_{y=1}^m \epsilon(\gcd(x,y)) \sum\limits_{i=1}^{\left\lfloor \frac{n}{x} \right\rfloor}\sum\limits_{j=1}^{\left\lfloor \frac{m}{y} \right\rfloor}1\\ =\sum\limits_{x=1}^n\sum\limits_{y=1}^m\sum\limits_{d|\gcd(x,y)}\mu(d)\left\lfloor \frac{n}{x} \right\rfloor\left\lfloor \frac{m}{y} \right\rfloor\\ =\sum\limits_{d=1}^{\min(n,m)}\sum\limits_{x=1}^{\left\lfloor \frac{n}{d} \right\rfloor}\sum\limits_{y=1}^{\left\lfloor \frac{m}{d} \right\rfloor}\mu(d)\left\lfloor \frac{n}{xd} \right\rfloor\left\lfloor \frac{m}{yd} \right\rfloor\\ =\sum\limits_{d=1}^{\min(n,m)}\mu(d)(\sum\limits_{x=1}^{\left\lfloor \frac{n}{d} \right\rfloor}\left\lfloor \frac{n}{xd} \right\rfloor)(\sum\limits_{y=1}^{\left\lfloor \frac{m}{d} \right\rfloor}\left\lfloor \frac{m}{yd} \right\rfloor) \]

公式 2.1.2.5
  • \(\sigma_1(xy)=\sum\limits_{i|x}\sum\limits_{j|y}\frac{jx}{i}[\gcd(i,j)=1]\)​​

    证明:同样还是构造一一对应来证明,构造方法和上面证明 \(2.1.2.2\) 相同,设:

    \[x=\prod\limits_{i=1}^np_i^{\alpha_i},y=\prod\limits_{j=1}^np_j^{\beta_j}\\ i=\prod\limits_{j=1}^kp_{i_j}^{a_{i_j}},j=\prod_{i=1}^{n-k}p_{j_i}^{a_{j_i}} \]

    我们看 \(\frac{jx}i\)​ 的值表示出来是多少,我们发现这个值是:

    \[\prod\limits_{j=1}^k p_{i_j}^{\alpha_{i_j}-a_{i_j}}\times \prod\limits_{i=1}^{n-k}p_{j_i}^{\alpha_{j_i}+a_{j_i}} \]

    这个 \(i,j\)​ 对应的因子是 \(\prod_{j=1}^kp_{i_j}^{a_{i_j}}\prod_{p_{j_i}}^{n-k}p_{j_i}^{\alpha_{j_i}+a_{j_i}}\)​,不难发现,这个因子与上面相比,右边相同,左边相乘是 \(x\)​​​ ,所以这两个因子是一一对应的。显然这个式子是正确的。

公式 2.1.2.6
  • \(\sum\limits_{i=1}^n\sigma_1(i)=\sum\limits_{i=1}^ni\left\lfloor \frac{n}{i} \right\rfloor\)

    证明:

    \[\sum\limits_{i=1}^n\sigma_1(i)=\sum\limits_{i=1}^n\sum\limits_{j=1}^ij[j|i]=\sum\limits_{j=1}^n\sum\limits_{i=1}^{\left\lfloor \frac{n}{j} \right\rfloor}j=\sum\limits_{i=1}^nj\left\lfloor \frac{n}{j} \right\rfloor \]

公式 2.1.2.7
  • \(\sum\limits_{i=1}^n\sum\limits_{j=1}^n\sigma_1(ij)=\sum\limits_{d=1}^n\mu(d)d(\sum\limits_{i=1}^{\left\lfloor \frac{n}{d} \right\rfloor}\sigma_1(i))^2\)​

    证明:

    \[\sum\limits_{i=1}^n\sum\limits_{j=1}^n\sigma_1(ij)=\sum\limits_{i=1}^n\sum\limits_{j=1}^n\sum\limits_{x|i}\sum\limits_{y|j}\frac{jx}{y}[\gcd(x,y)=1]\\ =\sum\limits_{x=1}^{n}\sum\limits_{y=1}^n\sum\limits_{i=1}^{\left\lfloor \frac{n}{x} \right\rfloor}\sum\limits_{j=1}^{\left\lfloor \frac{n}{y} \right\rfloor}jx\times \epsilon(\gcd(x,y))\\ =\sum\limits_{d=1}^n\mu(d)d \sum\limits_{x=1}^{\left\lfloor \frac{n}{d} \right\rfloor}\sum\limits_{y=1}^{\left\lfloor \frac{n}{d} \right\rfloor}\sum\limits_{i=1}^{\left\lfloor \frac{n}{xd} \right\rfloor}\sum\limits_{j=1}^{\left\lfloor \frac{n}{yd} \right\rfloor}jx\\ =\sum\limits_{d=1}^{n}\mu(d)d\sum\limits_{x=1}^{\left\lfloor \frac{n}{d} \right\rfloor}x\left\lfloor \frac{n}{xd} \right\rfloor\sum\limits_{y=1}^{\left\lfloor \frac{n}{d} \right\rfloor}\sum\limits_{j=1}^{\left\lfloor \frac{n}{yd} \right\rfloor}j\\ =\sum\limits_{d=1}^{n}\mu(d)d\sum\limits_{x=1}^{\left\lfloor \frac{n}{d} \right\rfloor}\sigma_1(x)\sum\limits_{y=1}^{\left\lfloor \frac{n}{d} \right\rfloor}\sigma_1(y)\\ =\sum\limits_{d=1}^{n}\mu(d)d(\sum\limits_{i=1}^{\left\lfloor \frac{n}{d} \right\rfloor}\sigma_1(i))^2 \]

公式 2.1.2.8
  • \(\sum\limits_{i=1}^n\mu^2(i)=\sum\limits_{i=1}^{\sqrt n}\mu(i)\times\left\lfloor \frac{n}{i^2} \right\rfloor\)

    这个公式需要构造来证明,具体证明过程请参照例题 \(2.2.4\)。

公式 2.1.2.9
  • \(\sum\limits_{i=1}^n\mu^2(i)\left\lfloor \sqrt{\frac{n}{i}} \right\rfloor\)​​

    这个东西的证明和上面类似,我们同样考虑构造。考虑 \(1\) 到 \(n\) 内所有不能被完全平方数整除的数组成的集合 \(P\) ,那么 \(1\) 到 \(n\) 内的每一个数都可以表示成 \(xy^2\) 的形式,其中 \(x\in P,y\le \sqrt{\frac nx}\),上面的式子其实等价于 \(\sum\limits_{p\in P}\left\lfloor \sqrt{\frac{n}{i}} \right\rfloor\)​,根据 \(y\) 的取值范围,不难发现这个式子的正确性。

公式 2.1.2.10
  • \(\sum\limits_{i=1}^n\sum\limits_{j=1}^n[\gcd(i,j)=1]=\sum\limits_{d=1}^n\mu(d)\left\lfloor \frac{n}{d} \right\rfloor=2S_{\phi}(\left\lfloor \frac{n}{d} \right\rfloor)-1\)

    证明:

    这里只证明后面的那个式子。

    设 \(f(n)=\sum\limits_{i=1}^n\sum\limits_{j=1}^n[\gcd(i,j)=1],g(n)=\sum\limits_{i=1}^n\sum\limits_{j=1}^i[\gcd(i,j)=1]\),那么 \(g(n)=S_{\phi}(i)\),那么容易验证有:\(f(n)=2g(n)-1\) ,减 \(1\) 是因为 \((1,1)\) 被算重了。

公式 2.1.2.11
  • \(\prod\limits_{i=1}^n\prod\limits_{j=1}^n\gcd^2(i,j)=(\prod\limits_{i=1}^nd^{S_{\phi}(\left\lfloor \frac{n}{d} \right\rfloor)})\)

    证明:

    \[\prod\limits_{i=1}^n\prod\limits_{j=1}^n\gcd{^2}(i,j)=\prod\limits_{i=1}^nd^{\sum\limits_{i=1}^n\sum\limits_{j=1}^n[\gcd(i,j)=d]}\\ =\prod\limits_{i=1}^nd^{\sum\limits_{i=1}^{\left\lfloor \frac{n}{d} \right\rfloor}\sum\limits_{j=1}^{\left\lfloor \frac{n}{d} \right\rfloor}\gcd(i,j)=1} \]

    由公式 \(2.1.2.10\) 可以知道,该公式成立。

2.2 例题

上面的每一个公式按顺序依次标号。

2.2.1 洛谷P3935

运用上面公式 \(2.1.2.3\)​​​ 即可。

#include<bits/stdc++.h>
#define dd double
#define ld long double
#define ll long long
#define uint unsigned int
#define ull unsigned long long
#define N number
#define M number
using namespace std;

const int INF=0x3f3f3f3f;
const int mod=998244353;

template<typename T> inline void read(T &x) {
    x=0; int f=1;
    char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c == '-') f=-f;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    x*=f;
}

ll l,r;

inline int Solve(ll k){
    if(k<1) return 0;
    int ans=0;
    for(ll i=1,j;i<=k;i=j+1){
        j=k/(k/i);
        ans=1ll*(ans+1ll*k/i*(j-i+1)%mod)%mod;
    }
    return ans;
}

int main(){
    read(l);read(r);
    printf("%d\n",((Solve(r)-Solve(l-1))%mod+mod)%mod);
    return 0;
}

2.2.2 洛谷P3327

公式 \(2.1.2.4\)​

代码:

#include<bits/stdc++.h>
#define dd double
#define ld long double
#define ll long long
#define uint unsigned int
#define ull unsigned long long
#define N 50010
#define M number
using namespace std;

const int INF=0x3f3f3f3f;

template<typename T> inline void read(T &x) {
    x=0; int f=1;
    char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c == '-') f=-f;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    x*=f;
}

bool NotPrime[N];
int Prime[N],tail,Mu[N],SumMu[N];

inline void Getmu(int n){
    NotPrime[1]=1;Mu[1]=1;
    for(int i=2;i<=n;i++){
        if(!NotPrime[i]) Prime[++tail]=i,Mu[i]=-1;
        for(int j=1;j<=tail&&i*Prime[j]<=n;j++){
            int k=i*Prime[j];NotPrime[k]=1;
            if(i%Prime[j]==0){Mu[k]=0;break;}
            else Mu[k]=Mu[i]*Mu[Prime[j]];
        }
    }
    for(int i=1;i<=n;i++) SumMu[i]=SumMu[i-1]+Mu[i];
}

ll f[N];

inline ll Get(int k){
    ll ans=0;
    for(int i=1,j;i<=k;i=j+1){
        j=k/(k/i);ans+=(k/i)*(j-i+1);
    }
    return ans;
}

inline ll Solve(int n,int m){
    int minn=min(n,m);
    ll ans=0;
    for(int i=1,j;i<=minn;i=j+1){
        int j1=n/(n/i),j2=m/(m/i);j=min(j1,j2);
        ans+=(SumMu[j]-SumMu[i-1])*f[n/i]*f[m/i];
    }
    return ans;
}

int t;

int main(){
    read(t);Getmu(50000);
    for(int i=1;i<=50000;i++) f[i]=Get(i);
    while(t--){
        int n,m;read(n);read(m);
        printf("%lld\n",Solve(n,m));
    }
    return 0;
}

2.2.3 51nod1220

公式 \(2.1.2.7\)

代码:

#include<bits/stdc++.h>
#define dd double
#define ld long double
#define ll long long
#define int long long
#define uint unsigned int
#define ull unsigned long long
#define N 1000010
#define M number
using namespace std;

const int INF=0x3f3f3f3f;
const int mod=1e9+7;

template<typename T> inline void read(T &x) {
    x=0; int f=1;
    char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c == '-') f=-f;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    x*=f;
}

map<int,ll> Map,f;
const ll inv2=500000004;

inline ll CalcSumSigma_1(int n){
    ll nowans=0;
    for(int i=1,j;i<=n;i=j+1){
        j=n/(n/i);
        nowans=(nowans+1ll*(n/i)*(i+j)%mod*(j-i+1)%mod*inv2%mod)%mod;
    }
    return nowans;
}

int Prime[N],F[N],SumF[N],tail,MAXN;
bool NotPrime[N];

inline void GetSumF(){
    int n=1000000;MAXN=n;
    NotPrime[1]=1;F[1]=1;
    for(int i=2;i<=n;i++){
        if(!NotPrime[i]) Prime[++tail]=i,F[i]=-i;
        for(int j=1,k;j<=tail&&(k=i*Prime[j])<=n;j++){
            NotPrime[k]=1;
            if(i%Prime[j]==0){F[k]=0;break;}
            else F[k]=F[Prime[j]]*F[i]%mod;
        }
    }
    for(int i=1;i<=n;i++) SumF[i]=(SumF[i-1]+F[i])%mod;
}

inline ll CalcSumF(int n){
    if(n<=MAXN) return SumF[n];
    if(f[n]) return f[n];
    ll now=(n>=1);
    for(int i=2,j;i<=n;i=j+1){
        j=n/(n/i);
        now=(now-1ll*CalcSumF(n/i)*(i+j)%mod*(j-i+1)%mod*inv2%mod)%mod;
    }
    f[n]=now;
    return now;
}

int n;

inline void GetSumSigma_1(){
    for(int i=1,j;i<=n;i=j+1){
        j=n/(n/i);
        ll val=CalcSumSigma_1(n/i)%mod;
        Map[n/i]=val*val%mod;
    }
}

inline void PreWork(){
    GetSumSigma_1();GetSumF();
}

signed main(){
    // freopen("my.in","r",stdin);
    // freopen("my.out","w",stdout);
    read(n);
    PreWork();
    // cout<<"here\n";
    // for(int i=1;i<=100;i++){
    //     printf("%lld\n",SumF[i]);
    // }
    ll ans=0;
    for(int i=1,j;i<=n;i=j+1){
        j=n/(n/i);
        // printf("i:%lld\n",i);
        // cout<<Map[n/i]<<endl;
        // cout<<(CalcSumF(j)-CalcSumF(i-1))<<endl;
        ans=(ans+1ll*(CalcSumF(j)-CalcSumF(i-1))*Map[n/i]%mod)%mod;
    }
    printf("%lld\n",(ans%mod+mod)%mod);
    return 0;
}

2.2.4 洛谷P4318

不难发现,答案具有可二分性。我们规定,如果一个数不能被完全平方数整除,则称其合法,否则称其不合法。那么 \(n\) 以内的合法的数一共有多少呢?不难发现,答案应该是:

\[\sum\limits_{i=1}^n\mu^2(i) \]

即为 \(1\) 到 \(n\) 中所有 \(\mu(x)\) 不为 \(0\) 的数。

我们考虑用容斥来计算这个东西,不难发现这个东西其实也是可以这样计算的:

含 \(0\) 个质数的平方的倍数减去含 \(1\) 个质数的平方的倍数加上含 \(2\) 个质数平方的倍数......,考虑莫比乌斯函数的定义,我们发现上面这个式子其实也是:

\[\sum\limits_{i=1}^{i\times i\le n}\mu(i)\times\left\lfloor \frac{n}{i^2} \right\rfloor \]

所以我们就可以二分这个答案,然后在 \(O(\sqrt n)\) 的时间复杂度内判断合不合法。

代码:

#include<bits/stdc++.h>
#define dd double
#define ld long double
#define ll long long
#define uint unsigned int
#define ull unsigned long long
#define N 60010
#define M number
using namespace std;

const int INF=0x3f3f3f3f;

template<typename T> inline void read(T &x) {
    x=0; int f=1;
    char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c == '-') f=-f;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    x*=f;
}

int Prime[N],tail,Mu[N];
bool NotPrime[N];

inline void PreWork(int n){
    NotPrime[1]=1;Mu[1]=1;
    for(int i=2;i<=n;i++){
        if(!NotPrime[i]) Prime[++tail]=i,Mu[i]=-1;
        for(int j=1,k;j<=tail&&(k=i*Prime[j])<=n;j++){
            NotPrime[k]=1;
            if(i%Prime[j]==0) break;
            else Mu[k]=-Mu[i];
        }
    }
}

int t;

inline bool Check(int mid,int k){
    int res=0;
    for(ll i=1;i*i<=mid;i++){
        res=res+Mu[i]*(mid/(i*i));
    }
    return res>=k;
}

int main(){
    // freopen("my.in","r",stdin);
    // freopen("my.out","w",stdout);
    PreWork(60000);
    read(t);
    while(t--){
        ll k;read(k);
        ll l=k,r=2*k;
        while(l<r){
            // cout<<"l"<<" "<<l<<endl;

            int mid=(l+r)>>1;
            if(Check(mid,k)) r=mid;
            else l=mid+1;
        }
        printf("%lld\n",l);
    }
}

2.2.5 SP5971 LCMSUM - LCM Sum

要求计算 \(\sum_{i=1}^nlcm(i,n)\) ,我们尝试化简这个东西:

\[\sum\limits_{i=1}^nlcm(i,n)=\sum\limits_{i=1}^n\frac{in}{\gcd(i,n)}=\sum\limits_{i=1}^n\sum\limits_{d|i,d|n}[\gcd(\frac di,\frac nd)=1]\times \frac{in}{d}\\ =\sum\limits_{d|n}\sum\limits_{i=1}^{\left\lfloor \frac{n}{d} \right\rfloor}in[\gcd(i,\frac nd)=1] \]

我们令 \(g(x)=\sum\limits_{i=1}^x[\gcd(i,x)=1]\times i\) 即在 \(1\) 到 \(x\) 总所有与 \(x\) 互质的数的个数,因为 \(\gcd(i,n)=1\Leftrightarrow\gcd(n-i,i)\) ,所以互质的数总是两两一对,且和为 \(n\) 。

所以这个和应该是 \(\frac{\phi(x)x}{2}\)。

所以上面那个式子可以化简为:

\[n\sum\limits_{d|n}\frac{\phi(d)d}{2} \]

我们可以用 \(n\log n\) 的时间复杂度完成这个事情。

这个地方有一点不太严谨,当 \(d=1\) 的时候注意 \(g(1)=1\),这个是个特殊的。

#include<bits/stdc++.h>
#define dd double
#define ld long double
#define ll long long
#define uint unsigned int
#define ull unsigned long long
#define N 1000100
#define M number
using namespace std;

const int INF=0x3f3f3f3f;

template<typename T> inline void read(T &x) {
    x=0; int f=1;
    char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c == '-') f=-f;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    x*=f;
}

int Prime[N],tail,Phi[N];
ll g[N],f[N];
bool NotPrime[N];

inline void PreWork(int n){
    NotPrime[1]=1;Phi[1]=1;
    for(int i=2;i<=n;i++){
        if(!NotPrime[i]) Prime[++tail]=i,Phi[i]=i-1;
        for(int j=1,k;j<=tail&&(k=i*Prime[j])<=n;j++){
            NotPrime[k]=1;
            if(i%Prime[j]==0){
                Phi[k]=Phi[i]*Prime[j];break;
            }
            else Phi[k]=Phi[i]*Phi[Prime[j]];
        }
    }
    // for(int i=1;i<=5;i++) printf("%d ",Phi[i]);puts("");
    g[1]=1;
    for(int i=2;i<=n;i++) g[i]=1ll*Phi[i]*i/2;
    // for(int i=1;i<=5;i++) printf("%lld ",g[i]);puts("");
    for(int i=1;i<=n;i++)
        for(int j=i;j<=n;j+=i) f[j]+=g[i];
    for(int i=1;i<=n;i++) f[i]*=i;
}

int t,n;

int main(){
    // freopen("my.in","r",stdin);
    // freopen("my.out","w",stdout);
    PreWork(1000000);
    read(t);
    while(t--){
        read(n);printf("%lld\n",f[n]);
    }
}//

2.2.6 P3768 简单的数学题

首先我们尝试化简式子:

\[\sum\limits_{i=1}^n\sum\limits_{j=1}^nij\gcd(i,j)=\sum\limits_{k=1}^n\sum\limits_{k|i,i\le n}\sum\limits_{k|j,j\le n}ijk[\gcd(\left\lfloor \frac{k}{i} \right\rfloor,\left\lfloor \frac{k}{j} \right\rfloor)=1]\\ =\sum\limits_{k=1}^n\sum\limits_{i=1}^{\left\lfloor \frac{n}{k} \right\rfloor}\sum\limits_{j=1}^{\left\lfloor \frac{n}{k} \right\rfloor}ijk^3[\gcd(i,j)=1] \]

令 \(g(n)=\sum_{i=1}^n\sum_{j=1}^nij[\gcd(i,j)=1]\),我们可以得到:

\[g(n)=\sum\limits_{i=1}^ni\sum\limits_{j=1}^nj[\gcd(i,j)=1]=[n\ge 1]+\sum\limits_{i=2}^n\frac{\phi(i)i}{2} \]

所以原来的式子我们可以化简为:

\[\sum\limits_{k=1}^nk^3g(\left\lfloor \frac{n}{k} \right\rfloor) \]

由于 \(n\) 是 \(1e9\) 级别的,所以我们可以用杜教筛筛一下 \(g(n)\) 。然后用整除分块。因为杜教筛也是整除分块计算的,所以杜教筛外面套一个整除分块没有问题。

莫比乌斯函数扩展

莫比乌斯函数非卷积形式。

对于数论函数和完全积性函数 \(t\) 且 \(t(1)=1\) ,有以下等价式子:

\[f(n)=\sum\limits_{i=1}^nt(i)g(\left\lfloor \frac{n}{i} \right\rfloor)\Leftrightarrow g(n)=\sum\limits_{i=1}^nt(i)\mu(i)f(\left\lfloor \frac{n}{i} \right\rfloor) \]

  • 证明:

    \[g(n)=\sum\limits_{i=1}^nt(i)\mu(i)f(\left\lfloor \frac{n}{i} \right\rfloor)\\ =\sum\limits_{i=1}^nt(i)\mu(i)\sum\limits_{j=1}^{\left\lfloor \frac{n}{i} \right\rfloor}t(j)g(\left\lfloor \frac{n}{ij} \right\rfloor)\\ =\sum\limits_{d=1}^n\sum\limits_{i|d} t(i)\mu(i)t(\frac{d}{i})g(\left\lfloor \frac{n}{d} \right\rfloor)\\ =\sum\limits_{d=1}^ng(\left\lfloor \frac{n}{d} \right\rfloor)t(d)\sum\limits_{i|d}t(i)\\ =\sum\limits_{d=1}^ng(\left\lfloor \frac{n}{d} \right\rfloor)t(d)\epsilon(d)\\ =g(n) \]

标签:lfloor,frac,limits,分块,sum,rfloor,反演,莫比,left
来源: https://www.cnblogs.com/TianMeng-hyl/p/15674560.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有