莫比乌斯函数与欧拉函数

积性函数

两个互质的整数m,n;
若满足 f ( n m ) = f ( n ) ∗ f ( m ) f(nm)=f(n)*f(m) f(nm)=f(n)f(m)
这就是一积性函数

两个任意的整数m,n;
若满足 f ( n m ) = f ( n ) ∗ f ( m ) f(nm)=f(n)*f(m) f(nm)=f(n)f(m)
这就是一完全积性函数

欧拉函数


欧拉函数:在n范围内与n互质的个数
ϕ ( n ) = ∑ i = 1 n [ g c d ( i , n ) = 1 ] \phi(n)=\sum_{i=1}^n[gcd(i,n)=1] ϕ(n)=i=1n[gcd(i,n)=1]
n = p 1 1 ∗ p 2 2 . . . ∗ p m m n=p_1^1*p_2^2...*p_m^m n=p11p22...pmm

所以: ϕ ( n ) = ∑ i = 1 n [ g c d ( i , n ) = 1 ] = n ∗ ( 1 − 1 / p i ) ∗ ( 1 − 1 / p 2 ) . . . ∗ ( 1 − 1 / p m ) \phi(n)=\sum_{i=1}^n[gcd(i,n)=1]=n*(1-1/p_i)*(1-1/p_2)...*(1-1/p_m) ϕ(n)=i=1n[gcd(i,n)=1]=n(11/pi)(11/p2)...(11/pm)

ϕ ( 1 ) = 1 \phi(1)=1 ϕ(1)=1
代码如下:
模板

莫比乌斯函数与欧拉函数

莫比乌斯函数

莫比乌斯函数定义

这,是莫比乌斯函数的定义,这时候有人就要问了:

“兄弟兄弟,这式子太麻烦了,我看不懂啊,能不能换个更加通俗易懂的方法?”
“有的兄弟,有的,像这样的通俗解法还有好几个”

莫比乌斯函数完整定义的通俗表达:
1)μ(1)=1;
2)当n存在平方因子时,μ(n)=0;
3)当n是素数或奇数个不同素数之积时,μ(n)=-1;
4)当n是偶数个不同素数之积时,μ(n)=1。

如何求解莫比乌斯函数 我们根据定义,直接进行质因数分解。碰到平方因子直接返回 0 ,
否则每次碰到质因数乘一个 -1 即可。总体时间复杂度是 O(√n)

但是平常做题经常会用到很多个数的莫比乌斯函数值,那么我们就不能用这种方法求了。我
们知道莫比乌斯函数是积性函数,所以很方便使用线性筛求解莫比乌斯函数

μ ( 1 ) = 1 \mu(1)=1 μ(1)=1
找到一个质数 x , 则 μ ( x ) = − 1 找到一个质数x,则\mu(x)=-1 找到一个质数x,μ(x)=1
对于一个和数 x ,如果有平方因子, μ ( x ) = 0 , 否则利用积性函数性质计算 对于一个和数x,如果有平方因子,\mu(x)=0,否则利用积性函数性质计算 对于一个和数x,如果有平方因子,μ(x)=0,否则利用积性函数性质计算

我们再来把欧拉函数加入进去

1.若 n 是素数, φ ( n ) = n − 1 φ(n)=n-1 φ(n)=n1,这个由定义可知。
2.若 n = pk , φ ( n ) = p k − p k − 1 φ( n ) = pk - pk-1 φ(n)=pkpk1 ,这个在之前已经得出。
3.若 n 是奇数, φ ( 2 n ) = φ ( n ) φ( 2n ) = φ( n ) φ(2n)=φ(n),因为 n 和 2 互质, φ ( 2 ) = 1 φ(2)=1 φ(2)=1,由积性函数的性质可得
4. ∑ d ∣ n ϕ ( d ) = n \sum_{d|n}\phi(d)=n dnϕ(d)=n
5. 若 p ∣ n p | n pn p 2 ∣ n p2 | n p2∣n ,则\ ϕ ( n ) = ϕ ( n / p ) = p \phi(n)=\phi(n/p)=p ϕ(n)=ϕ(n/p)=p
这时我们就能用以上性质用线性筛筛欧拉函数了

模板代码:

整合后代码:

int cnt=0,prime[N],miu[N],phi[N];
bool vis[N]; 
void ola(int n){
	vis[1]=miu[1]=phi[1]=1;
	for(int i=2;i<=n;i++){
		if(!vis[i]){
			prime[++cnt]=i;
			miu[i]=-1;
			phi[i]=i-1;
		}
		for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
			vis[i*prime[j]]=1;
			if(i%prime[j]==0){
				
				miu[i*prime[j]]=0;
				phi[i*prime[j]]=phi[i]*prime[j];
				
				break;
			}
			miu[i*prime[j]]=-miu[i];
			phi[i*prime[j]]=phi[i]*phi[prime[j]];
		}
	}
}

例题:

Farey数列

AC代码


注意数据量,别忘开long long!!!


#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e6+10;
int cnt=0,prime[N],phi[N];
bool vis[N]; 
void ola(int n){
	vis[1]=phi[1]=1;
	for(int i=2;i<=n;i++){
		if(!vis[i]){
			prime[++cnt]=i;
			phi[i]=i-1;
		}
		
		for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
			vis[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]];
			//phi[i*prime[j]]=phi[i]*(prime[j]-1);
		}
	}
}
int f[N];
signed main(){
    ola(N);
    
    f[1]=0;
    for(int i=2;i<=N;i++){
        f[i]=f[i-1]+phi[i];
    }
    
    int n;
	while(cin>>n&&n!=0){
	    cout<<f[n]<<"\n";
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值