数论\to 模范
本文未经说明全是整数,全是整除。
aifoson 括号
\([1]=1,[1=0]=0,[[1=0]=0]=1\).
diliclate 卷积
符号 \(\Huge *\)
\(\large{f*g}\) 表示两个数论函数的 dlk 卷积。
一般卷积的形式:
因为 2.,所以枚举的值是要整除 \(x\) 的才能保证,数论卷积式子:
- dlk 卷积满足交换律,结合律
1.易证,因为所有卷积的形式都是对称的。
是u论函数
- 值域,定义域 \(\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\)。
以上都是完全积性函数。
- 完全积性函数满足 \(f(ab)=f(a)f(b)\)
\(\varphi(n)\) 表示 \([1,n]\) 中与 \(n\) 互质的数的个数(\(\varphi(n)=\mu(n)*id(n)\))。
\(\mu(n)\) 表示  ,但是看不懂。
,但是看不懂。
以上都是积性函数。
- 积性函数满足 \((a,b)=1\to f(ab)=f(a)f(b)\)。
积性函数 \(f\) 的一些性质
- \(f(1)=1\),由 \(f(1)=f(1)f(1)\) 可得。
- \(f(x)=f\left(p_{1}^{k_{1}}\right) f\left(p_{2}^{k_{2}}\right) \ldots f\left(p_{m}^{k_{m}}\right)\),由各质因子互质可得。
- 两个积性函数的 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) \]
- 若存在 \(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. 嵌入式莫比乌斯反演
- \([n|m]\sum\limits_{d|\frac nm}\mu(d)=[n=m]\)
证明:
有一个显然的东西:\([n|m][\frac nm=1]=[n=m]\),因为一个数整除另一个数又除另一个数等于 \(1\)(即 \(\not =0\)),这两个数肯定相等。
然后再看这个式子:
展开:
将 \(n=\frac nm\) 代入得
从中间可以得到的副产品
- 
\[\boxed{\sum\limits_{d|n}\mu(d)=[n=1]} \]
但是是最有用的式子。
B. 约数的莫比乌斯反演
- \(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\),所以
C. 倍数的莫比乌斯反演
- \(F(n)=\sum\limits_{n|d}f(d)\),则 \(f(n)=\sum\limits_{n|d}\mu(\frac dn)F(d)\)
ben 说做题基本不会用,待补。
一些题目
线性筛会了就可以开始做题了,筛质数的过程中可以顺便按照其定义处理 \(\mu\) 或 \(\varphi\)。
GCD
\(T\) 组询问,求
\(1\le n,m\le 5\times 10^4\)。
记 \(n<m\)
由 10. 得
考虑 \(d,x,y\) 的取值范围都为 \([1,\frac nm]\),可以把 \(d\) 移到前面去
到这里就可以 \(O(n)\) 算了,但是会 TLE。
我们需要一个新东西,整除分块
然后就可以做到 \(O(\sqrt n)\) 算了,总时间复杂度 \(O(T\sqrt n)\)。
P4450 双亲数
求
\(1\le t\le n,m\le 10^6\)。
题目存在一个隐含的条件,对于能计数的情况,一定有 \(t|x,t|y\),所以
两边除以 \(t\)
然后就是上题的板子了。
点击查看代码
#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\) 组询问,求
\(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\) 求下式的值:
uint 自然溢出。
对于 \(100\%\) 的数据,\(1 \leq n \leq 10^7\),\(1 \leq k \leq 2^{31}\)。
P4240 毒瘤之神的考验
给 \(n,m\),求
对 998244353 取模,多测。
\(n,m\le 10^5,T\le 10^4\)
拆式子与根号分治思想的极致融合。
设 \(n\le m\)。
先要知道一个经典的式子:
然后拆式子
枚举 \(d=\gcd(i,j)\)
后面那个直接莫反拆掉,把枚举扔外面
这个式子就很好看了,设
则原式为
\(f,g\) 直接预处理是可以的,因为 \(g\) 的数量是 \(n\log n\) 级别的,且 \(g\) 可以直接递推:
所以预处理 \(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)\),这个三元函数就可以数论分块了,即
\(h\) 也可以递推
否则可以得到 \(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;
}

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号