1、积性函数:任意互素的两个数m、n,满足f(mn)=f(m)f(n)
常见积性函数: φ , μ , σ , d φ,μ,σ,d φ,μ,σ,d
φ:欧拉函数
μ:莫比乌斯函数
d:约束个数函数 d = ∑ d ∣ n 1 d=\sum_{d|n}1 d=∑d∣n1
σ:约束和函数 σ ( n ) = ∑ d ∣ n d σ(n)=\sum_{d|n}d σ(n)=∑d∣nd
2、完全积性函数:任意两个数m、n,满足f(mn)=f(m)f(n)
常见完全积性函数: ϵ , I , i d ϵ,I,id ϵ,I,id
ϵ ϵ ϵ:元函数 ϵ ( n ) = [ n = 1 ] ϵ(n)=[n=1] ϵ(n)=[n=1]
I I I:恒等函数 I ( n ) = 1 I(n)=1 I(n)=1
i d id id:单位函数 i d ( n ) = n id(n)=n id(n)=n
定义:两个数论函数 f 和 g 的卷积为 ( f ∗ g ) ( n ) = ∑ d ∣ n f ( d ) g ( n d ) (f*g)(n)=\sum_{d|n}f(d)g(\frac nd) (f∗g)(n)=∑d∣nf(d)g(dn)
性质:和乘法差不多,满足交换律、结合律、分配律
1、交换律:交换的顺序,只是枚举的约数的顺序出现变化,每个约数的贡献不变
2、元函数: f ∗ ϵ = f f*\epsilon =f f∗ϵ=f
定义: φ ( n ) \varphi (n) φ(n)指小于等于n且与n互素的正整数的个数
公式: φ ( n ) = n ∏ i = 1 k ( 1 − 1 p i ) \varphi(n)=n \prod_{i=1}^{k} (1-\frac 1{p_i}) φ(n)=n∏i=1k(1−pi1),k为不同的质因子的个数
性质:
1、当n>2时, φ ( n ) \varphi (n) φ(n)为偶数
2、当n>1时,小于n的数中与n互质的数的总和是: φ ( n ) n 2 \frac {\varphi (n) n}{2} 2φ(n)n
3、n的所有因子的欧拉函数之和等于n: ∑ d ∣ n φ ( d ) = n \sum_{d|n}\varphi (d)=n ∑d∣nφ(d)=n
1、直接求欧拉函数,也可以先筛出素数,然后用素数去化简
ll euler(ll n)
{
ll ret=n,a=n;
for(ll i=2;i*i<=a;++i)
{
if(a%i==0)
{
ret=ret/i*(i-1);
while(a%i==0)
a/=i;
}
}
if(a>1)
ret=ret/a*(a-1);
return ret;
}
2、埃氏筛
int phi[maxn];
void euler(int n)
{
for(int i=1;i<=n;++i)
phi[i]=i;
for(int i=2;i<=n;++i)
{
//相等表示i是质数。不相等,说明是合数,已经被更新过了
if(phi[i]==i)
{
//遍历i的倍数,i是质因子,据公式更新
for(int j=i;j<=n;j+=i)
phi[j]=phi[j]/i*(i-1);
}
}
}
3、欧拉筛求欧拉函数
const int N=1e5;
int visit[N+10],phi[N+10],prime[N+10],cnt;
void euler()
{
phi[1]=1,cnt=0; //1要特判
for (int i=2;i<=N;i++)
{
if(!visit[i]) //这代表i是质数
{
prime[++cnt]=i;
phi[i]=i-1;
}
for (int j=1;j<=cnt&&prime[j]*i<=N;j++)
{
visit[i*prime[j]]=1; //把这个合数标记掉
if (i%prime[j]==0)
{
//若prime[j]是i的质因子,据计算公式,i已经包括i*prime[j]的所有质因子
phi[i*prime[j]]=phi[i]*prime[j];
break; //break用于这样能保证每个数只会被自己最小的因子筛掉一次
}
else //与质数不是倍数关系,就是互质
phi[i*prime[j]]=phi[i]*phi[prime[j]]; //积性函数
}
}
}
不带注释
const int N=1e5;
int visit[N+10],phi[N+10],prime[N+10],cnt;
void euler()
{
phi[1]=1,cnt=0;
for (int i=2;i<=N;i++)
{
if(!visit[i])
{
prime[++cnt]=i;
phi[i]=i-1;
}
for (int j=1;j<=cnt&&prime[j]*i<=N;j++)
{
visit[i*prime[j]]=1;
if (i%prime[j]==0)
{
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
else
phi[i*prime[j]]=phi[i]*phi[prime[j]];
}
}
}
定义:每一个n可以分解为: n = p 1 k 1 p 2 k 2 … p s k s n=p_1^{k_1}p_2^{k_2}\dots p_s^{k_s} n=p1k1p2k2…psks
μ ( n ) = { 1 ( n = 1 ) 0 ( ∃ k i ≥ 2 ) ( − 1 ) s ( ∀ k i = 1 ) \mu(n)=\begin{cases} 1 &(n=1) \\ 0 &(\exists k_i \ge2)\\ (-1)^s &(\forall k_i=1) \end{cases} μ(n)=⎩⎪⎨⎪⎧10(−1)s(n=1)(∃ki≥2)(∀ki=1)
性质:
1、 ∑ d ∣ n u ( d ) = [ n = 1 ] \sum_{d|n}u(d)=[n=1] ∑d∣nu(d)=[n=1]
2、 ∑ d ∣ n μ ( d ) n d = φ ( n ) \sum_{d|n} \mu(d) \frac nd=\varphi(n) ∑d∣nμ(d)dn=φ(n)
证明:利用欧拉函数的性质: ∑ d ∣ n φ ( d ) = n \sum_{d|n}\varphi (d)=n ∑d∣nφ(d)=n
写成卷积形式: φ ∗ I = i d \varphi *I=id φ∗I=id
化简: φ ∗ I ∗ μ = i d ∗ μ \varphi *I*\mu=id*\mu φ∗I∗μ=id∗μ ⟶ \longrightarrow ⟶ φ ∗ ϵ = i d ∗ μ \varphi *\epsilon=id*\mu φ∗ϵ=id∗μ
φ ( n ) = ∑ d ∣ n u ( d ) i d ( n d ) = ∑ d ∣ n u ( d ) n d \varphi (n)=\sum_{d|n}u(d)id(\frac nd)=\sum_{d|n}u(d)\frac nd φ(n)=∑d∣nu(d)id(dn)=∑d∣nu(d)dn
线性筛莫比乌斯函数
const int N=5e4+5;
int prime[maxn],visit[maxn];
int mu[maxn],cnt;
void Mobius()
{
memset(visit,0,sizeof(visit));
memset(mu,0,sizeof(mu));
cnt=0,mu[1]=1,visit[1]=1;
for(int i=2;i<N;++i)
{
if(!visit[i])
prime[++cnt]=i,mu[i]=-1;
for(int j=1;j<=cnt&&i*prime[j]<N;++j)
{
visit[i*prime[j]]=1;
if(i%prime[j]==0)
break;
mu[i*prime[j]]=-mu[i];
}
}
}
形式一:设f(n)是一个任意的函数, F ( n ) = ∑ d ∣ n f ( d ) F(n)=\sum_{d|n}f(d) F(n)=∑d∣nf(d)
反演可得: f ( n ) = ∑ d ∣ n μ ( d ) F ( n d ) f(n)=\sum_{d|n}\mu (d)F(\frac nd) f(n)=d∣n∑μ(d)F(dn)
证明: F ( n ) = ∑ d ∣ n f ( d ) = f ∗ I = F(n)=\sum_{d|n}f(d)=f*I= F(n)=∑d∣nf(d)=f∗I=
F ∗ μ = f ∗ I ∗ μ = f ∗ ( I ∗ u ) F*\mu =f*I*\mu=f*(I*u) F∗μ=f∗I∗μ=f∗(I∗u)
利用性质: ∑ d ∣ n u ( d ) = [ n = 1 ] \sum_{d|n}u(d)=[n=1] ∑d∣nu(d)=[n=1]
因此: I ∗ μ = ϵ I*\mu =\epsilon I∗μ=ϵ
f ∗ ( I ∗ μ ) = f ∗ ϵ = f = F ∗ μ = ∑ d ∣ n u ( d ) F ( n d ) f*(I*\mu)=f*\epsilon=f=F* \mu=\sum_{d|n}u(d)F(\frac nd) f∗(I∗μ)=f∗ϵ=f=F∗μ=d∣n∑u(d)F(dn)
形式二:设f(n)是一个任意的函数, F ( n ) = ∑ n ∣ d f ( d ) F(n)=\sum_{n|d}f(d) F(n)=∑n∣df(d)
反演可得: f ( n ) = ∑ n ∣ d μ ( d n ) F ( d ) f(n)=\sum_{n|d}\mu (\frac dn)F(d) f(n)=n∣d∑μ(nd)F(d)
用途:计算积性函数的前缀和,时间复杂度为 O ( n 2 3 ) O(n^{\frac 23}) O(n32)
1、需要计算: ∑ i = 1 n f ( i ) \sum_{i=1}^nf(i) ∑i=1nf(i)
2、构造两个积性函数h和g满足: h = f ∗ g h=f*g h=f∗g
3、推导:先计算 ∑ i = 1 n h ( i ) \sum_{i=1}^n h(i) ∑i=1nh(i),设 S ( n ) S(n) S(n)为 f ( i ) f(i) f(i)前缀和
∑ i = 1 n h ( i ) = ∑ i = 1 n ∑ d ∣ i g ( d ) f ( i d ) \sum_{i=1}^n h(i)=\sum_{i=1}^n\sum_{d|i}g(d)f(\frac id) i=1∑nh(i)=i=1∑nd∣i∑g(d)f(di)
= ∑ d = 1 n g ( d ) ∑ i = 1 n d f ( i ) =\sum_{d=1}^n g(d)\sum_{i=1}^{\frac nd}f(i) =d=1∑ng(d)i=1∑dnf(i)
= ∑ d = 1 n g ( d ) S ( n d ) =\sum_{d=1}^n g(d) S(\frac nd) =d=1∑ng(d)S(dn)
= g ( 1 ) S ( n ) + ∑ d = 2 n g ( d ) S ( n d ) =g(1)S(n)+\sum_{d=2}^n g(d) S(\frac nd) =g(1)S(n)+d=2∑ng(d)S(dn)
因此可得:
g ( 1 ) S ( n ) = ∑ i = 1 n h ( i ) − ∑ d = 2 n g ( d ) S ( n d ) g(1)S(n)=\sum_{i=1}^n h(i) - \sum_{d=2}^n g(d) S(\frac nd) g(1)S(n)=i=1∑nh(i)−d=2∑ng(d)S(dn)
例一:求 S ( n ) = ∑ i = 1 n μ ( i ) S(n)=\sum_{i=1}^n\mu(i) S(n)=∑i=1nμ(i)
我们很容易想到: μ ∗ I = ϵ \mu*I=\epsilon μ∗I=ϵ,对 ϵ \epsilon ϵ求求前缀和就是1
g ( 1 ) S ( n ) = ∑ i = 1 n h ( i ) − ∑ d = 2 n g ( d ) S ( ⌊ n d ⌋ ) g(1)S(n)=\sum_{i=1}^n h(i) - \sum_{d=2}^n g(d) S(\lfloor \frac nd \rfloor) g(1)S(n)=i=1∑nh(i)−d=2∑ng(d)S(⌊dn⌋)
该式可以化简为:
S ( n ) = 1 − ∑ d = 2 n S ( ⌊ n d ⌋ ) S(n)=1 - \sum_{d=2}^n S(\lfloor \frac nd \rfloor) S(n)=1−d=2∑nS(⌊dn⌋)
例二:求 S ( n ) = ∑ i = 1 n φ ( i ) S(n)=\sum_{i=1}^n\varphi(i) S(n)=∑i=1nφ(i)
我们知道: φ ∗ I = i d \varphi *I=id φ∗I=id
因此同样可以化简为:
S ( n ) = ∑ i = 1 n i − ∑ d = 2 n S ( ⌊ n d ⌋ ) S(n)=\sum_{i=1}^n i- \sum_{d=2}^n S(\lfloor \frac nd \rfloor) S(n)=i=1∑ni−d=2∑nS(⌊dn⌋)
例三:求 S ( n ) = ∑ i = 1 n i × φ ( i ) S(n)=\sum_{i=1}^{n}i \times \varphi(i) S(n)=∑i=1ni×φ(i)
(1)我们观察: f ( i ) = i × φ ( i ) f(i)=i \times \varphi(i) f(i)=i×φ(i)
(2)然后考虑: f ∗ g f*g f∗g的卷积形式: h = f ∗ g = ∑ d ∣ n d × φ ( d ) g ( n d ) h=f*g=\sum_{d|n}d\times \varphi(d)\ g(\frac nd) h=f∗g=∑d∣nd×φ(d) g(dn)
(3)很明显,我们想要消去这个d,因此取g=id
化简: h = ∑ d ∣ n d × φ ( d ) n d = ∑ d ∣ n n × φ ( d ) = n 2 h=\sum_{d|n}d\times \varphi(d)\ \frac nd=\sum_{d|n}n\times \varphi(d)=n^2 h=∑d∣nd×φ(d) dn=∑d∣nn×φ(d)=n2
(4)因此可以得到:
S ( n ) = ∑ i = 1 n i 2 − ∑ d = 2 n S ( ⌊ n d ⌋ ) S(n)=\sum_{i=1}^n i^2- \sum_{d=2}^n S(\lfloor \frac nd \rfloor) S(n)=i=1∑ni2−d=2∑nS(⌊dn⌋)
题意:求欧拉函数和莫比乌斯函数的前缀和
分析:模板题。需要使用:快读、unordered_map记忆化、整除分块不能全用long long
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <queue>
#include <vector>
#include <set>
#include <map>
#include <unordered_map>
#include <cstring>
#include <string>
#include <cmath>
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define per(i,b,a) for (int i=b; i>=a; --i)
#define mes(a,b) memset(a,b,sizeof(a))
#define mp make_pair
#define ll long long
#define pb push_back
#define pii pair<int,int>
#define pll pair<ll,ll>
#define ls (rt<<1)
#define rs ((rt<<1)|1)
#define isZero(d) (abs(d) < 1e-8)
using namespace std;
const int maxn=6e6+10,INF=0x3f3f3f3f;
const int mod=1e9+7;
inline int read()
{
int X=0,w=1;
char c=getchar();
while (c<'0'||c>'9')
{
if (c=='-') w=-1;
c=getchar();
}
while (c>='0'&&c<='9')
X=X*10+c-'0',c=getchar();
return X*w;
}
int T,n;
const int N=6e6;
ll phi[maxn];
int visit[maxn],prime[maxn],mu[maxn],cnt;
inline void init()
{
mu[1]=1,phi[1]=1,cnt=0;
for(int i=2;i<=N;++i)
{
if(!visit[i])
prime[++cnt]=i,phi[i]=i-1,mu[i]=-1;
for(int j=1;j<=cnt&&i*prime[j]<=N;++j)
{
visit[i*prime[j]]=1;
if(i%prime[j]==0)
{
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
phi[i*prime[j]]=phi[i]*phi[prime[j]];
mu[i*prime[j]]=-mu[i];
}
}
for(int i=1;i<=N;++i)
phi[i]+=phi[i-1],mu[i]+=mu[i-1];
}
unordered_map<int,ll> mphi;
unordered_map<int,int> mmu;
inline ll calphi(int n)
{
if(n<=N)
return phi[n];
if(mphi[n])
return mphi[n];
int l=2,r;
ll ans=1ll*(1+n)*n/2;
while(l<=n)
{
r=n/(n/l);
ans-=1ll*(r-l+1)*calphi(n/l);
l=r+1;
}
return mphi[n]=ans;
}
inline int calmu(int n)
{
if(n<=N)
return mu[n];
if(mmu[n])
return mmu[n];
int l=2,r;
ll ans=1;
while(l<=n)
{
r=n/(n/l);
ans-=1ll*(r-l+1)*calmu(n/l);
l=r+1;
}
return mmu[n]=ans;
}
int main()
{
init();
T=read();
while(T--)
{
n=read();
printf("%lld %d\n",calphi(n),calmu(n));
}
return 0;
}