数论\to 模范

本文未经说明全是整数,全是整除。

aifoson 括号

\([1]=1,[1=0]=0,[[1=0]=0]=1\).

diliclate 卷积

符号 \(\Huge *\)

\(\large{f*g}\) 表示两个数论函数的 dlk 卷积。

一般卷积的形式:

\[(f*g)(x)=\sum_{i=-\infty}^{\infty}f(i)g(x-i) \]

因为 2.,所以枚举的值是要整除 \(x\) 的才能保证,数论卷积式子:

\[(f*g)(x)=\sum_{i|x}^{}f(i)g(\frac xi) \]

  1. dlk 卷积满足交换律,结合律

1.易证,因为所有卷积的形式都是对称的。

是u论函数

  1. 值域,定义域 \(\in \mathbb Z\)

常见数论函数

\(I(x)\):恒等函数,函数值恒为 \(1\)
\(ϵ(x)/e(x)\):单位元函数,\(e(x)=[x=1]\),有性质 \(e*f=f\)
\(id(x)\):单位函数,\(id(x)=x\)
\(id^n(x)\):幂函数,\(id^n(x)=x^n\)
以上都是完全积性函数。

  1. 完全积性函数满足 \(f(ab)=f(a)f(b)\)

\(\varphi(n)\) 表示 \([1,n]\) 中与 \(n\) 互质的数的个数(\(\varphi(n)=\mu(n)*id(n)\))。
\(\mu(n)\) 表示 ,但是看不懂。
以上都是积性函数。

  1. 积性函数满足 \((a,b)=1\to f(ab)=f(a)f(b)\)

积性函数 \(f\) 的一些性质

  1. \(f(1)=1\),由 \(f(1)=f(1)f(1)\) 可得。
  2. \(f(x)=f\left(p_{1}^{k_{1}}\right) f\left(p_{2}^{k_{2}}\right) \ldots f\left(p_{m}^{k_{m}}\right)\),由各质因子互质可得。
  3. 两个积性函数的 dlk 卷积还是积性函数。
    证明:
    🐍 \(f_1,f_2\) 为积性函数,\((a,b)=1\),记 \(g(x)=f_1(x)*f_2(x)=\sum\limits_{d|x}f_1(d)f_2(\frac xd)\)

    \[g(a)g(b)=\sum\limits_{d|a} f_1(d)f_2(\frac ad)\sum\limits_{t|b} f_1(t)f_2(\frac bt)=\sum\limits_{d|a}\sum\limits_{t|b} f_1(d)f_2(\frac ad)f_1(t)f_2(\frac bt) \]

    由于 \(a,b\) 互质,所以 \(d,t\) 互质,两个求和可以合并:

    \[g(a)g(b)=\sum\limits_{dt|ab} f_1(dt)f_2(\frac {ab}{dt})=g(ab) \]

  4. 若存在 \(g*f=e\),则称 \(g\)\(f\),且 \(g\) 也是积性函数,这可以顺便证明 \(\mu(n)\) 是积性函数。

\(\mu\) 的推导

以下默认函数为积性函数。

设两单变量函数 \(F,f\) 满足 \(F(n)=\sum\limits_{d|n}f(d)\)
那么有 \(F(n)=\sum\limits_{d|n}I(d)f(d)=I(n)*f(n)\)
变形一下 \(f=I^{-1}*F\),于是我们只需要求出 \(I^{-1}\) 即可。
大佬Möbius把 \(I^{-1}\) 命名为 \(μ\)
这里有个小技巧,研究一个积性函数,先研究其在质数的幂时的表现。
先看 \(\mu(p^k)\) 的值。

  • \(k=0\),由 5.,\(\mu(1)=1\)
  • \(k=1\)\(\mu(p)*I(p)=\sum\limits_{d|p}\mu(d)I(\frac pd)=\mu(1)I(p)+\mu(p)I(1)=1+\mu(p)=e(p)=0\),所以 \(\mu(p)=-1\)
  • \(k>1\)\(\mu(p^k)*I(p^k)=\sum\limits_{d|p^k}\mu(d)I(\frac{p^k}{d})=e(p^k)=0\),消去 \(I\)(因为 \(I\) 都等于 \(1\)),\(\sum\limits_{d|p^k}\mu(d)=\mu(1)+\mu(p)+\mu(p^2)+\cdots+\mu(p^k)=0\)
    再用数学归纳法不难得到 \(\mu(p^k)=0\)

根据 4.,对于 \(n=p_1^{k_1}p_2^{k_2}\ldots p_s^{k_s}\)\(\mu(n)=\mu(p_1^{k_1})\mu(p_2^{k_2})\ldots\mu(p_s^{k_s})\)
又因为 \(k>1\)\(\mu(p^k)=0\),所以当 \(\exists i,k_i>1\) 时,\(\mu(n)=0\),否则 \(\mu(n)=(-1)^s\)
这下就好理解 了。

莫反公式

A. 嵌入式莫比乌斯反演

  1. \([n|m]\sum\limits_{d|\frac nm}\mu(d)=[n=m]\)

证明:
有一个显然的东西:\([n|m][\frac nm=1]=[n=m]\),因为一个数整除另一个数又除另一个数等于 \(1\)(即 \(\not =0\)),这两个数肯定相等。
然后再看这个式子:

\[\mu*I=e \]

展开:

\[\sum\limits_{d|n}\mu(d)I(\frac nd)=e(n) \]

\[\sum\limits_{d|n}\mu(d)=e(n) \]

\(n=\frac nm\) 代入得

\[\sum\limits_{d|\frac nm}\mu(d)=e(\frac nm)=[\frac nm=1]=\frac{[n=m]}{[n|m]}(这里不是很严谨但是比较好理解) \]

\[[n|m]\sum\limits_{d|\frac nm}\mu(d)=[n=m] \]

从中间可以得到的副产品

  1. \[\boxed{\sum\limits_{d|n}\mu(d)=[n=1]} \]

但是是最有用的式子。

B. 约数的莫比乌斯反演

  1. \(F(n)=\sum\limits_{d|n}f(d)\),则 \(f(n)=\sum\limits_{d|n}\mu(d)F(\frac nd)\)

证明:
\(F\) 的定义,有 \(F=I*f\),即 \(f=\mu * F\),所以

\[f(n)=\mu(n)*F(n)=\sum\limits_{d|n}\mu(d)F(\frac nd)=\sum\limits_{d|n}F(d)\mu(\frac nd) \]

C. 倍数的莫比乌斯反演

  1. \(F(n)=\sum\limits_{n|d}f(d)\),则 \(f(n)=\sum\limits_{n|d}\mu(\frac dn)F(d)\)

ben 说做题基本不会用,待补。

一些题目

线性筛会了就可以开始做题了,筛质数的过程中可以顺便按照其定义处理 \(\mu\)\(\varphi\)

GCD

\(T\) 组询问,求

\[\sum\limits_{x=1}^n\sum\limits_{y=1}^m[\gcd(x,y)=1] \]

\(1\le n,m\le 5\times 10^4\)

\(n<m\)

由 10. 得

\[\begin{aligned} \sum\limits_{x=1}^n\sum\limits_{y=1}^m[\gcd(x,y)=1]&=\sum\limits_{x=1}^n\sum\limits_{y=1}^m\sum\limits_{d|\gcd(x,y)\to d|x,d|y}\mu(d) \end{aligned}\]

考虑 \(d,x,y\) 的取值范围都为 \([1,\frac nm]\),可以把 \(d\) 移到前面去

\[\begin{aligned} \sum\limits_{x=1}^n\sum\limits_{y=1}^m[\gcd(x,y)=1]&=\sum\limits_{d=1}^n\mu(d)\sum\limits_{x|n}^n 1\sum\limits_{y|m}^m 1 \\ &=\sum\limits_{d=1}^n\mu(d)\sum\limits_{x|n}^n 1\sum\limits_{y|m}^m 1\\ &=\sum\limits_{d=1}^n\mu(d)\lfloor\frac nd\rfloor \lfloor\frac md\rfloor \end{aligned}\]

到这里就可以 \(O(n)\) 算了,但是会 TLE。

我们需要一个新东西,整除分块

然后就可以做到 \(O(\sqrt n)\) 算了,总时间复杂度 \(O(T\sqrt n)\)

P4450 双亲数

\[\sum\limits_{x=1}^n\sum\limits_{y=1}^m[\gcd(x,y)=t] \]

\(1\le t\le n,m\le 10^6\)

题目存在一个隐含的条件,对于能计数的情况,一定有 \(t|x,t|y\),所以

\[\begin{aligned} \sum\limits_{x=1}^n\sum\limits_{y=1}^m[\gcd(x,y)=t]&=\sum\limits_{t|x}^n\sum\limits_{t|y}^m[\gcd(x,y)=t] \end{aligned}\]

两边除以 \(t\)

\[\begin{aligned} \sum\limits_{x=1}^n\sum\limits_{y=1}^m[\gcd(x,y)=t]&=\sum\limits_{1|x\to x=1}^{\frac nt}\sum\limits_{1|y\to y=1}^{\frac mt}[\gcd(x,y)=1] \end{aligned}\]

然后就是上题的板子了。

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int pr[80003],cnt,n,m,d,ans;
bool isp[1000003];
int mu[1000003];
int premu[1000003];
void sieve(){
	premu[1]=mu[1]=1;
	for(int i=2;i<=n;i++){
		if(!isp[i])	pr[++cnt]=i,mu[i]=-1;
		for(int j=1;i*pr[j]<=n;j++){
			isp[i*pr[j]]=1;
			mu[i*pr[j]]=(i%pr[j]?-mu[i]:0);
			if(i%pr[j]==0) break;
		}
		premu[i]=premu[i-1]+mu[i];
	}
}
signed main(){
	cin>>n>>m>>d;
	if(n<m) swap(n,m);
	sieve();
	for(int i=1;i<=m/d;i++)
		ans+=mu[i]*(n/d/i)*(m/d/i);
	cout<<ans;
	return 0;
}

P3455 [POI2007] ZAP-Queries

上题带多组询问。

加个数论分块即可,时间复杂度 \(O(T\sqrt n)\)

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int pr[80003],cnt,n,m,d,ans;
bool isp[1000003];
int mu[1000003];
int premu[1000003];
void sieve(){
	premu[1]=mu[1]=1;
	for(int i=2;i<=50000;i++){
		if(!isp[i])	pr[++cnt]=i,mu[i]=-1;
		for(int j=1;j<=cnt&&i*pr[j]<=50000;j++){
			isp[i*pr[j]]=1;
			mu[i*pr[j]]=(i%pr[j]?-mu[i]:0);
			if(i%pr[j]==0) break;
		}
		premu[i]=premu[i-1]+mu[i];
	}
}
void solve(){
	cin>>n>>m>>d;
	if(n<m) swap(n,m);
	ans=0; n/=d; m/=d;
	for(int l=1,r=0;l<=m;l=r+1){
		r=min(n/(n/l),m/(m/l));
		ans+=(premu[r]-premu[l-1])*(n/l)*(m/l);
	}
	cout<<ans<<'\n';
}
int T;
signed main(){
	cin>>T; sieve();
	while(T--) solve();
	return 0;
}

P2522 [HAOI2011] Problem b

\(T\) 组询问,求

\[\sum\limits_{x=a}^b\sum\limits_{y=c}^d[\gcd(x,y)=k] \]

\(1\le T,a,b,c,d,k\le 5\times 10^4\)

可以用二维差分,则答案为 \(solve(b,d)-solve(a-1,d)-solve(b,c-1)+solve(a-1,c-1)\),时间复杂度 \(O(T\sqrt n)\)

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int pr[80003],cnt,ans;
bool isp[1000003];
int mu[1000003];
int premu[1000003];
void sieve(){
	premu[1]=mu[1]=1;
	for(int i=2;i<=50000;i++){
		if(!isp[i])	pr[++cnt]=i,mu[i]=-1;
		for(int j=1;j<=cnt&&i*pr[j]<=50000;j++){
			isp[i*pr[j]]=1;
			mu[i*pr[j]]=(i%pr[j]?-mu[i]:0);
			if(i%pr[j]==0) break;
		}
		premu[i]=premu[i-1]+mu[i];
	}
}
int solve(int n,int m,int d){
	if(n<m) swap(n,m);
	ans=0; n/=d; m/=d;
	for(int l=1,r=0;l<=m;l=r+1){
		r=min(n/(n/l),m/(m/l));
		ans+=(premu[r]-premu[l-1])*(n/l)*(m/l);
	}
	return ans;
}
int T,a,b,c,d,k;
signed main(){
	cin>>T; sieve();
	while(T--){
		cin>>a>>b>>c>>d>>k;
		cout<<solve(b,d,k)-solve(a-1,d,k)-solve(b,c-1,k)+solve(a-1,c-1,k)<<'\n';
	}
	return 0;
}

P6156 简单题 / 加强版 P6222

題面為加强版。

給出 \(k\)\(T\) 組詢問给你 \(n\) 求下式的值:

\[\sum\limits_{i=1}^n\sum\limits_{j=1}^n(i+j)^k\mu^2(\gcd(i,j))\gcd(i,j) \]

uint 自然溢出。

对于 \(100\%\) 的数据,\(1 \leq n \leq 10^7\)\(1 \leq k \leq 2^{31}\)

P4240 毒瘤之神的考验

\(n,m\),求

\[\sum\limits_{i=1}^n\sum\limits_{j=1}^m \varphi(ij) \]

对 998244353 取模,多测。

\(n,m\le 10^5,T\le 10^4\)

拆式子与根号分治思想的极致融合。

\(n\le m\)

先要知道一个经典的式子:

\[\varphi(ij)=\frac{\varphi(i)\varphi(j)\gcd(i,j)}{\varphi(\gcd(i,j))} \]

然后拆式子

\[\begin{aligned} \sum\limits_{i=1}^n\sum\limits_{j=1}^m \varphi(ij)&=\sum\limits_{i=1}^n\sum\limits_{j=1}^m \frac{\varphi(i)\varphi(j)\gcd(i,j)}{\varphi(\gcd(i,j))} \end{aligned}\]

枚举 \(d=\gcd(i,j)\)

\[\begin{aligned} \sum\limits_{i=1}^n\sum\limits_{j=1}^m \frac{\varphi(i)\varphi(j)\gcd(i,j)}{\varphi(\gcd(i,j))}&=\sum\limits_{d=1}^n\sum\limits_{i=1}^n\sum\limits_{j=1}^m \frac{\varphi(i)\varphi(j)d[\gcd(i,j)=d]}{\varphi(d)}\\ &=\sum\limits_{d=1}^n\frac{d}{\varphi(d)}\sum\limits_{i=1}^n\sum\limits_{j=1}^m \varphi(i)\varphi(j)[\gcd(i,j)=d]\\ &=\sum\limits_{d=1}^{n}\frac{d}{\varphi(d)}\sum\limits_{i=1}^{n/d}\sum\limits_{j=1}^{m/d} \varphi(id)\varphi(jd)[\gcd(i,j)=1]\\ \end{aligned}\]

后面那个直接莫反拆掉,把枚举扔外面

\[\begin{aligned} \sum\limits_{d=1}^{n}\frac{d}{\varphi(d)}\sum\limits_{i=1}^{n/d}\sum\limits_{j=1}^{m/d} \varphi(id)\varphi(jd)[\gcd(i,j)=1]&=\sum\limits_{d=1}^{n}\frac{d}{\varphi(d)}\sum\limits_{i=1}^{n/d}\sum\limits_{j=1}^{m/d} \varphi(id)\varphi(jd)\sum\limits_{t\mid i,t\mid j}\mu(t)\\ &=\sum\limits_{d=1}^{n}\frac{d}{\varphi(d)}\sum\limits_{t=1}^{n/d}\mu(t)\sum\limits_{i=1}^{n/d}\sum\limits_{j=1}^{m/d} \varphi(idt)\varphi(jdt)\\ &=\sum\limits_{t=1}^{n}\sum\limits_{d\mid t}\frac{d\mu(\frac{t}{d})}{\varphi(d)}\sum\limits_{i=1}^{n/t}\varphi(it)\sum\limits_{j=1}^{m/t} \varphi(jt)\\ \end{aligned}\]

这个式子就很好看了,设

\[f(n)=\sum\limits_{d|n}\frac{d\mu(\frac{n}{d})}{\varphi(d)},g(n,k)=\sum\limits_{i=1}^{n}\varphi(ik) \]

则原式为

\[\sum\limits_{t=1}^n f(t)g(n/t,t)g(m/t,t) \]

\(f,g\) 直接预处理是可以的,因为 \(g\) 的数量是 \(n\log n\) 级别的,且 \(g\) 可以直接递推:

\[g(n,k)=g(n-1,k)+\varphi(nk) \]

所以预处理 \(f,g\) 时间复杂度 \(O(n\log n)\)

由于原式并不好整除分块,也不能暴力预处理全部信息,所以我们只能考虑分治。

设阈值为 \(B\),记原式为三元函数 \(h(a,b,n)=\sum\limits_{t=1}^n f(t)g(a,t)g(b,t)\),考虑当 \(a,b\le B\) 时直接暴力预处理答案,时空复杂度 \(O(nB^2)\),这个三元函数就可以数论分块了,即

\[\sum\limits_{n/l=m/l,n/r=m/r}h(n/l,m/l,r)-h(n/l,m/l,l-1) \]

\(h\) 也可以递推

\[h(a,b,n)=h(a,b,n-1)+f(n)g(a,n)g(b,n) \]

否则可以得到 \(n/a\ge B,a\le n/B\),暴力统计答案,时间复杂度 \(O(n/B)\)

综上,时间复杂度 \(O(n\log n+nB^2+T(\sqrt n+\frac{n}{B}))\),取 \(B=\sqrt[3]{T}=22\),可以通过,500~700 ms,空间复杂度 \(O(n\log n+nB^2)\)

点击查看代码
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const int maxn=1e5+7;
const int B=24;
const int maxb=B+2;
const int N=1e5;
const int mod=998244353;
bool st;
int mu[maxn],phi[maxn],pr[maxn],pcnt;
ll f[maxn],inv[maxn];
bool isp[maxn];
vector<ll>g[maxn],h[maxb][maxb];
bool ed;
void solve(){
    int n,m,l=1,r;
    cin>>n>>m;
    if(n>m) swap(n,m);
    ll ans=0;
    for(;l<=m/B;l++)
        ans=(ans+f[l]*g[l][n/l]%mod*g[l][m/l]%mod)%mod;
    for(;l<=n;l=r+1){
        r=min(n/(n/l),m/(m/l));
        ans=(ans+h[n/l][m/l][r]-h[n/l][m/l][l-1]+mod)%mod;
    }
    cout<<ans<<'\n';
}
signed main(){
    cerr<<(&ed-&st)/1048576.0<<" MB\n";
    inv[1]=mu[1]=phi[1]=1;
    for(int i=2;i<=N;i++){
        inv[i]=(mod-mod/i)*inv[mod%i]%mod;
        if(!isp[i]) pr[++pcnt]=i,mu[i]=-1,phi[i]=i-1;
        for(int j=1;j<=pcnt&&i*pr[j]<=N;j++){
            isp[i*pr[j]]=1;
            if(i%pr[j]==0){
                mu[i*pr[j]]=0;
                phi[i*pr[j]]=pr[j]*phi[i];
                break;
            }
            mu[i*pr[j]]=-mu[i];
            phi[i*pr[j]]=phi[i]*phi[pr[j]];
        }
    }
    for(int i=1;i<=N;i++){
        g[i].resize(N/i+2); g[i][0]=0;
        for(int j=1;j<=N/i;j++)
            g[i][j]=(g[i][j-1]+phi[i*j])%mod;
    }
    for(int i=1;i<=N;i++)
        for(int j=1;j<=N/i;j++)
            f[j*i]=(f[j*i]+i*mu[j]*inv[phi[i]]%mod+mod)%mod;
    for(int j=1;j<=B;j++){
        for(int k=1;k<=B;k++){
            h[j][k].resize(N/k+7); h[j][k][0]=0;
            for(int i=1;i<=N/k;i++)
                h[j][k][i]=(h[j][k][i-1]+f[i]*g[i][j]%mod*g[i][k]%mod)%mod;
        }
    }
    int TEST;
    cin>>TEST;
    while(TEST--){
        solve();
    }
    return 0;
}
posted @ 2024-02-21 08:58  view3937  阅读(36)  评论(0)    收藏  举报
Title