数论浅谈

数论函数

定义域为整数,值域为复数的函数

积性函数:若 \(\gcd(a,b)=1\) ,则\(f(ab)=f(a)+f(b)\)

感觉正确的结论

若有数论函数

\[f(n)=\sum_{d|n}g(d) \cdot k(n) \]

\(g,k\)均为积性函数,则\(f\)为积性函数。

证明:
显然,有无\(k\)不干扰\(f\)是否积性,所以把\(f(n)\)简化为\(f(n)=\sum_{d|n}g(n)\)

对于\(g\)函数:设\(x,y\)使得\(\gcd(x,y)=1\)
\(x=\prod_{i=1}^{s_x} {px_i}^{\alpha x_i},y=\prod_{i=1}^{s_y} {py_i}^{\alpha y_i}\).
则有\(\forall i,j\ px_i\ne py_j\)

\[f(x\cdot y)=\sum_{d|x\cdot y} g(d)=\Big( \sum_{d|x}g(d) \Big) \cdot \Big(\sum_{d|y}g(d) \Big) = f(x)\cdot f(y) \]

草率地得证。

除数函数

\(\sigma_x(n)=\sum_{d|n}d^x\)
除数函数为积性函数。

欧拉函数 \(\varphi\)

\(\varphi(n)=\)表示不超过 \(n\) 且与 \(n\) 互质的正整数的个数

\[\varphi(n)=n\cdot \prod_{i=1}^{s}(1-\frac{1}{p_i}) \]

其中 \(n = {p_1}^{\alpha1} \cdot {p_2}^{\alpha2} \cdots {p_s}^{\alpha s} \cdot\)\(n\) 的标准分解。
由此易见 \(\text{Euler}\) 函数是积性函数。
同时满足\(n=\sum_{d|n}\varphi(d)\)

线性求 \(\text{Euler}\) 函数:

#define int long long
int phi[3000005];
int n=3000000;
bool mark[3000005];
int prime[1000005];
int tot;
void getphi()
{
	phi[1]=1;
	for(int i=2;i<=n;i++)
	{
		if(mark[i]==false)
		{
			prime[++tot]=i;
			phi[i]=i-1;
		}
		for(int j=1;j<=tot;j++)
		{
			if(i*prime[j]>n)
			{
				break;
			}
			mark[i*prime[j]]=true;
			if(i%prime[j]==0)
			{
				phi[i*prime[j]]=phi[i]*prime[j];
				break;
			}
			phi[i*prime[j]]=phi[i]*phi[prime[j]];
		}
	}
	for(int i=1;i<=n;i++)
	{
		phi[i]+=phi[i-1];
	}
}

\(\text{Mobius}\)函数 \(\mu(n)\)

\[\mu(n)= \begin{cases} 1&n=1\\ 0&n\text{ 含有平方因子}\\ (-1)^k&k\text{ 为 }n\text{ 的本质不同质因子个数}\ \end{cases} \]

证明:

\[\varepsilon(n)= \begin{cases} 1&n=1\\ 0&n\neq 1\ \end{cases} \]

其中 \(\displaystyle\varepsilon(n)=\sum_{d\mid n}\mu(d)\)\(\varepsilon=\mu*1\)

\(\displaystyle n=\prod_{i=1}^k{p_i}^{c_i},n'=\prod_{i=1}^k p_i\)

那么 \(\displaystyle\sum_{d\mid n}\mu(d)=\sum_{d\mid n'}\mu(d)=\sum_{i=0}^k C_k^i\cdot(-1)^k\)

根据二项式定理,易知该式子的值在 \(k=0\)\(n=1\) 时值为 \(1\) 否则为 \(0\) ,这也同时证明了 \(\displaystyle\sum_{d\mid n}\mu(d)=[n=1]\)

#define int long long
int mu[3000005];
int n=3000000;
bool mark[3000005];
int prime[1000005];
int tot;
void getmu()
{
	mu[1]=1;
	for(int i=2;i<=n;i++)
	{
		if(mark[i]==false)
		{
			prime[++tot]=i;
			mu[i]=-1;
		}
		for(int j=1;j<=tot;j++)
		{
			if(i*prime[j]>n)
			{
				break;
			}
			mark[i*prime[j]]=true;
			if(i%prime[j]==0)
			{
				mu[i*prime[j]]=0;
				break;
			}
			mu[i*prime[j]]=-mu[i];
		}
	}
}

\(\text{Dirichlet}\)卷积

\(\text{ID}:\text{ID(i)=i}\)
\(\text{1}:\text{1(i)=1}\)
定义两个数论函数的\(\text{Dirichlet}\)卷积为:

\[(f*g)(n)=\sum_{d|n}({f(d)\times g(\frac{n}{d})}) \]

性质:\(\text{Dirichlet}\)卷积满足交换律和结合律。
单位元:\(\varepsilon\)\(\varepsilon(n)=[n==1]\),任何函数卷\(\varepsilon\)都为其本身.
\(1*\mu=\varepsilon\)
\(\mu * \text{ID} = \varphi\)
\(1*\text{ID}=\sigma\)

莫比乌斯反演

公式:设 \(f(n),g(n)\) 为两个数论函数。
如果有

\[f(n)=\sum_{d\mid n}g(d) \]

那么有

\[g(n)=\sum_{d\mid n}\mu(\frac{n}{d})f(d) \]

证明:
原命题等价于:已知 \(f=g*1\) ,证明 \(g=f*\mu\)
显然: \(f*\mu=g*1*\mu= g*\varepsilon=g\) (其中 \(1*\mu=\varepsilon\)

同时,还有另一种\(\text{Mobius}\)反演:
如果有

\[f(n)=\sum_{n\mid d}g(d) \]

那么有

\[g(n)=\sum_{n\mid d}\mu(\frac{d}{n})f(d) \]

整除分块

当遇到形如

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

的柿子时。
可以采用\(O(\sqrt {n})\)复杂度的算法:整除分块
易证:对于部分连续的\(i\)\(\frac{n}{i}\)的值是相同的,考虑把它们合并计算,可以发现发现对于每一个值相同的块,它的最后一个数是n/(n/i)
简略证明:\(\frac{n}{i}\)就是所求的值,设为\(x\),那么可证对于值\(x\),它所在的块的最后一个数是\(\frac{n}{x}\)

  • 证明:反证法:对于数\(\frac{n}{x}+1\),它所在的块的值为\(\frac{n}{\frac{n}{x}+1}\),且\(\frac{n}{\frac{n}{x}+1}-x=\frac{x^2}{n+x}>0\)。$\therefore \(数\)\frac{n}{x}+1 \(和数\)\frac{n}{x}$不在同一个块中。
    然后,原命题得证。

所以,易得计算原式方法。

for(int l=1,r;l<=n;l=r+1)
{
    r=n/(n/l);
    ans+=(r-l+1)*(n/l);
}

P2257 YY的GCD

\(f(d)=\sum_{i=1}^{n}\sum_{i=1}^{m}[gcd(i,j)=d]\)
\(F(n)=\sum_{n\mid d}f(d)=\lfloor \frac{N}{n} \rfloor \times \lfloor \frac{M}{n} \rfloor\)
由莫比乌斯反演:\(f(n)=\sum_{n|d}\mu(\frac{d}{n})F(d)\)

\(Ans=\sum_{i=1}^{n}\sum_{i=1}^{m}[gcd(i,j)=prim]\)
\(=\sum_{p\in prim}\sum_{i=1}^{n}\sum_{i=1}^{m}[gcd(i,j)=p]\)
\(=\sum_{p\in prim}f(p)\)
\(=\sum_{p\in prim}\sum_{p|d}\mu(\frac{d}{p})F(d)\)
改为枚举\(\frac{d}{p}\)
\(Ans=\sum_{p\in prim}\sum_{d}^{min(\lfloor \frac{n}{p} \rfloor,\lfloor \frac{m}{p} \rfloor)}\mu(d)F(dp)\)
\(=\sum_{p\in prim}\sum_{d}^{min(\lfloor \frac{n}{p} \rfloor,\lfloor \frac{m}{p} \rfloor)}\mu(d) \times \lfloor \frac{N}{dp} \rfloor \times \lfloor \frac{M}{dp} \rfloor\)
\(dp=T,t=p\)
\(Ans=\sum_{t\in prim}\sum_{d}^{min(\lfloor \frac{n}{t} \rfloor,\lfloor \frac{m}{t} \rfloor)}\mu(\frac{T}{t}) \times \lfloor \frac{N}{T} \rfloor \times \lfloor \frac{M}{T} \rfloor\)
\(=\sum_{T=1}^{min(n,m)}\sum_{t\in prim,t|T}\mu(\frac{T}{t}) \times \lfloor \frac{N}{T} \rfloor \times \lfloor \frac{M}{T} \rfloor\)
\(=\sum_{T=1}^{min(n,m)}(\lfloor \frac{N}{T} \rfloor \times \lfloor \frac{M}{T} \rfloor) \times \sum_{t\in prim,t|T}\mu(\frac{T}{t})\)

代码:
//sum即为\(\sum_{t\in prim,t|T}\mu(\frac{T}{t})\)的前缀和

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int prime[10000005];
int mu[10000005];
ll f[10000005];
ll sum[10000005];
bool vis[10000005];
int cnt;
void init()
{
    mu[1]=1;
    for(int i=2;i<=10000000;i++)
    {
        if(vis[i]==false)
        {
            mu[i]=-1;
            prime[++cnt]=i;
        }
        for(int j=1;j<=cnt&&i*prime[j]<=10000000;j++)
        {
            vis[i*prime[j]]=true;
            if(i%prime[j]==0)
            {
                break;
            }
            mu[i*prime[j]]=-mu[i];
        }
    }
    for(int i=1;i<=cnt;i++)
    {
        for(int j=1;j*prime[i]<=10000000;j++)
        {
            f[j*prime[i]]+=mu[j];
        }
    }
    for(int i=1;i<=10000000;i++)
    {
        sum[i]=sum[i-1]+f[i];
    }
}
ll solve(int a,int b)//运用整除分块
{
    ll ans=0;
    if(a>b)
    {
        swap(a,b);
    }
    for(int l=1,r=0;l<=a;l=r+1)
    {
        r=min(a/(a/l),b/(b/l));
        ans+=(ll)(sum[r]-sum[l-1])*(a/l)*(b/l);
    }
    return ans;
}
signed main()
{
    init();
    int T;
    cin>>T;
    for(int i=1;i<=T;i++)
    {
        int a,b;
        scanf("%d %d",&a,&b);
        printf("%lld\n",solve(a,b));
    }
    return 0;
}

常用柿子

\[[\gcd(x,y)=1]=\sum_{d|\gcd(x,y)}\mu(d) \]

\[\sum_{i=1}^n\sum_{j=1}^m(\gcd(i,j))=\sum_{T=1}^{\min(n,m)}(\lfloor \frac{n}{T} \rfloor \lfloor \frac{m}{T} \rfloor \varphi(T)) \]

调和数

\(H_n=\sum_{k=1}^{n}\frac{1}{k}\)
\(H_n=\ln n\ + \gamma\ + o(1)\)
\(\sum_{d=1}^n \lfloor\frac{n}{d}\rfloor = \text{O}(n \log n)\)

杜教筛

快速求出\(\phi(n)=\sum_{i=1}^n \varphi(i)\)
由于\(\text{ID}=\varphi * 1\)
可得\(\frac{n(n+1)}{2}=\sum_{k=1}^n\sum_{d|k}\varphi(\frac{k}{d})\)
\(=\sum_{k=1}^n\sum_{d=1}^{\lfloor \frac{n}{k} \rfloor}\varphi(d)\)
\(\therefore \phi(n)=\frac{n(n+1)}{2}-\sum_{d=2}^n \phi(\lfloor \frac{n}{d} \rfloor)\)
右边为子问题,可以递归解决,再加整除分块,可以保证每个点被计算一遍
复杂度\(O(n^{\frac{3}{4}})\)

代码:

#include<bits/stdc++.h>
using namespace std;
#define re register
#define ll long long
#define N 5500000
ll phi[N+5];
int mu[N+5];
int prim[N+5];
bool mark[N+5];
int cnt;
unordered_map<int,ll> aphi;
unordered_map<int,int> amu;
void init()
{
	phi[1]=1;
	mu[1]=1;
	for(re int i=2;i<=N;i++)
	{
		if(mark[i]==false)
		{
			phi[i]=i-1;
			mu[i]=-1;
			prim[++cnt]=i;
		}
		for(re int j=1;j<=cnt;j++)
		{
			if(i*prim[j]>N)
			{
				break;
			}
			mark[i*prim[j]]=true;
			if(i%prim[j]==0)
			{
				phi[i*prim[j]]=phi[i]*prim[j];
				mu[i*prim[j]]=0;
				break;
			}
			phi[i*prim[j]]=phi[i]*phi[prim[j]];
			mu[i*prim[j]]=-mu[i];
		}
	}
	for(re int i=1;i<=N;i++)
	{
		phi[i]+=phi[i-1];
		mu[i]+=mu[i-1];
	}
}
ll getphi(int x)
{
	if(x<=N)
	{
		return phi[x];
	}
	if(aphi[x]!=0)
	{
		return aphi[x];
	}
	ll ans=(ll)x*(x+1)/2;
	for(int l=2,r=0;r!=2147483647&&l<=x;l=r+1)
	{
		r=x/(x/l);
		ans-=(ll)(r-l+1)*getphi(x/l);
	}
	return aphi[x]=ans;
}
int getmu(int x)
{
	if(x<=N)
	{
		return mu[x];
	}
	if(amu[x]!=0)
	{
		return amu[x];
	}
	int ans=1;
	for(int l=2,r=0;r!=2147483647&&l<=x;l=r+1)
	{
		r=x/(x/l);
		ans-=(r-l+1)*getmu(x/l);
	}
	return amu[x]=ans;
}
int main()
{
	init();
	int T;
	cin>>T;
	int x;
	for(int i=1;i<=T;i++)
	{
		scanf("%d",&x);
		printf("%lld %d\n",getphi(x),getmu(x));
	}
	return 0;
}

posted @ 2019-02-17 20:07  wasa855  阅读(469)  评论(0编辑  收藏  举报