欧拉函数.

知识点

函数–积性函数–完全积性函数

函数
函数的定义,如: f ( n , m ) = n m f(n,m)=nm f(n,m)=nm
函数其实就是一个含k个字母的表达式,用一个字母代替随时可以带入k个数进行计算。
积性函数
设一个函数f(n),如果 gcd ⁡ ( x , y ) = 1 , f ( x ) ∗ f ( y ) = f ( x y ) \gcd(x,y)=1,f(x)*f(y)=f(xy) gcd(x,y)=1,f(x)f(y)=f(xy)则称这个函数是积性函数,如:
常数函数—— f ( n ) = 1 f(n)=1 f(n)=1
单位函数—— f ( n ) = [ n = 1 ] f(n)=[n=1] f(n)=[n=1]
除数函数—— σ k ( n ) = ∑ d ∣ n d k \sigma_k(n)=\sum_{d|n}d^k σk(n)=dndk
完全积性函数
设一个函数f(n),对于任意的x,y如果 f ( x ) ∗ f ( y ) = f ( x y ) f(x)*f(y)=f(xy) f(x)f(y)=f(xy)则称这个函数是完全积性函数,如:
f ( n ) = 0 f(n)=0 f(n)=0
f k ( n ) = n k f_k(n)=n^k fk(n)=nk
常数函数—— f ( n ) = 1 f(n)=1 f(n)=1
单位函数—— f ( n ) = [ n = 1 ] f(n)=[n=1] f(n)=[n=1]

欧拉函数的简介

欧拉函数用符号 φ φ φ表示,内容如下:
φ ( n ) = ∑ i = 1 n [ gcd ⁡ ( i , n ) = 1 ] = n ( 1 − 1 p 1 ) ( 1 − 1 p 2 ) ⋯ ( 1 − 1 p m ) = n ( p 1 − 1 p 1 ) ( p 2 − 1 p 2 ) ⋯ ( p m − 1 p m ) φ(n)=\sum_{i=1}^{n}[\gcd(i,n)=1]=n(1-\frac{1}{p_1})(1-\frac{1}{p_2})\cdots(1-\frac{1}{p_m})=n(\frac{p_1-1}{p_1})(\frac{p_2-1}{p_2})\cdots(\frac{p_m-1}{p_m}) φ(n)=i=1n[gcd(i,n)=1]=n(1p11)(1p21)(1pm1)=n(p1p11)(p2p21)(pmpm1)(m是n的质因子个数)
求的是1~n范围内与n互质的数的个数
欧拉函数是一个积性函数,但不是完全积性函数,因为要是x与y有公因数,拆开则会多算一次,而x,y互质则没有这个问题,所以欧拉函数只是积性函数。

欧拉函数的求法

n ( p 1 − 1 p 1 ) ( p 2 − 1 p 2 ) ⋯ ( p m − 1 p m ) n(\frac{p_1-1}{p_1})(\frac{p_2-1}{p_2})\cdots(\frac{p_m-1}{p_m}) n(p1p11)(p2p21)(pmpm1)(m是n的质因子个数)这个式子求即可。
利用唯一分解定理求n的质因数。
但要注意程序要这样写: a n s = a n s / p ∗ ( p − 1 ) ans=ans/p*(p-1) ans=ans/p(p1) a n s = a n s ∗ ( p − 1 ) / p ans=ans*(p-1)/p ans=ans(p1)/p,不能写 a n s = a n s ∗ ( ( p − 1 ) / p ) ans=ans*((p-1)/p) ans=ans((p1)/p),因为(p-1)/p会出现循环小数,导致答案出错,因为ans初值为n,p是n的因数,所以可以整除。
代码:

int oula(int n){
	int m=sqrt(n),x=n,ans=n;
	for(int i=2;i<=m;i++){
		if(x%i==0){
			while(x%i==0){
				x/=i;
			}
			ans=ans/i*(i-1);
		}
	}
	if(x!=1){
		ans=ans/x*(x-1);
	}
	return ans;
} 

接近线性求欧拉函数

因为欧拉函数是一个积性函数,我们可以利用欧拉筛来进行递推,质数的欧拉为质数-1,在枚举前面质数筛掉合数时将筛掉合数的欧拉求出(ola[i*prime[j]]=ola[i]*ola[prime[j]]),但是特别要注意会出现一次i为prime[j]的倍数,可欧拉函数不是完全积性函数,所以要暴力求那一次的欧拉。
代码

for(int i=2;i<=1000000;i++){
		if(vis[i]==0){
			prime[++cnt]=i;
			ola[i]=i-1;
		}
		for(int j=1;j<=cnt && i*prime[j]<=1000000;j++){
			vis[i*prime[j]]=1;
			if(i%prime[j]==0){
				ola[i*prime[j]]=oula(i*prime[j]);
				break;
			}
			else{
				ola[i*prime[j]]=ola[i]*ola[prime[j]];
			}
		}
	}

莫比乌斯函数


如果n=1返回1,如果n没有平方因子,则返回-1的因子数次方,否则输出0
暴力的话,进行分解质因数,有平方因子返回0,否则每次乘上一个-1

例题

Farey数列

时间限制:1秒 内存限制:256M

题目描述

对于任何n≥2的整数n的Farey数列 F n F_n Fn是一组不可约有理数a/b,其中0<a<b≤n以及gcd(a,b)=1,按递增顺序排列。前几个是:
F ​ 2 F_​2 F2​ ={1/2}
F ​ 3 ​​ F_​3​​ F3​​ ={1/3,1/2,2/3}
F ​ 4 F​_4 F4​​ ={1/4,1/3,1/2,2/3,3/4}
F ​ 5 F_​5 F5​​ ={1/5,1/4,1/3,2/5,1/2,3/5,2/3,3/4,4/5}
你的任务是计算Farey数列F_​n中有多少个元素。

样例输入

2
3
4
5
0

样例输出

1
3
5
9

思路

可以发现,第n项的元素数就是上一项的加上 φ ( n ) φ(n) φ(n),也就是欧拉和,我们可以利用接近线性求欧拉和前缀和提前预处理出答案来解决这个问题。

代码

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
long long sum_ola[1000005];
int prime[1000005],vis[1000005],cnt=0,ola[1000005];
int oula(int n){
	int m=sqrt(n),x=n,ans=n;
	for(int i=2;i<=m;i++){
		if(x%i==0){
			while(x%i==0){
				x/=i;
			}
			ans=ans/i*(i-1);
		}
	}
	if(x!=1){
		ans=ans/x*(x-1);
	}
	return ans;
} 
int main(){
	for(int i=2;i<=1000000;i++){
		if(vis[i]==0){
			prime[++cnt]=i;
			ola[i]=i-1;
		}
		for(int j=1;j<=cnt && i*prime[j]<=1000000;j++){
			vis[i*prime[j]]=1;
			if(i%prime[j]==0){
				ola[i*prime[j]]=oula(i*prime[j]);
				break;
			}
			else{
				ola[i*prime[j]]=ola[i]*ola[prime[j]];
			}
		}
		sum_ola[i]=sum_ola[i-1]+ola[i];
	}
	int n;
	while(scanf("%d",&n) && n!=0){
		printf("%lld\n",sum_ola[n]);
	}
	return 0;
}

[SDOI2008] 沙拉公主的困惑

时间限制:2秒 内存限制:256M

题目描述

原题目废话太多,本人已省略 其实就是求区间[1,N!]中与M!沪指的数的数量对R取模。

样例输入

1 11
4 2

样例输出

1

提示

对于 100% 的数据, 1 ≤ M ≤ N ≤ 10 , 1 ≤ T ≤ 10 , 2 ≤ R ≤ 1 0 9 + 10 1≤M≤N≤10,1≤T≤10,2≤R≤10^9+10 1MN10,1T10,2R109+10 且 R 为质数。

思路

我们需要把N!和M!联系起来,
可以借助 g c d ( x , M ! ) = g c d ( x + k M ! , M ! ) = 1 gcd(x,M!)=gcd(x+kM!,M!)=1 gcd(x,M!)=gcd(x+kM!,M!)=1
在本题中,x+k·M!如果大于 N! 就失去了意义
由于x≤M!,k的取值范围[0,N!/M!-1]
也就是说,对于每一个 x ≤ M! 并且 gcd( x , M! )=1 的数字 x ,包括它自身的话,在1~N! 的范围内,x+k·M! 都和 M! 互质,一共有 N!/M! 个 x+k·M! 。那么有多少个这样的 x 呢? φ ( M ! ) φ(M!) φ(M!) 个。所以最终要输出的结果为:
N ! M ! φ ( M ! ) \frac{N!}{M!}φ(M!) M!N!φ(M!)
但是 φ(M!) 很难求,因为 M! 实在是太大了。注意,这里求欧拉函数时,不能直接求 φ ( M ! % R ) φ(M! \% R ) φ(M!%R),也就是说 φ ( x ) % R ≠ φ ( x % R ) % R φ(x) \% R ≠ φ(x \% R) \% R φ(x)%R=φ(x%R)%R
假设 M 是质数,那么我们可以想到,M 这个质数一定不可能是 (M-1)! 的质因数,也就是说 M 和 (M-1)! 互质。那么既然互质,欧拉函数是积性函数,那么我们可以得到:
φ ( M ! ) = φ ( M ) φ ( ( M − 1 ) ! ) = ( M − 1 ) φ ( ( M − 1 ) ! ) φ(M!)=φ(M)φ((M-1)!)=(M-1)φ((M-1)!) φ(M!)=φ(M)φ((M1)!)=(M1)φ((M1)!)
如果 M 是合数,相对于 (M-1)! ,M 并没有贡献新的质因数,所以:
所以可得:
φ ( M ! ) = M φ ( ( M − 1 ) ! ) φ(M!)=Mφ((M-1)!) φ(M!)=((M1)!)
至此,我们就可以线性求出 φ(M!) 了!首先使用欧拉筛筛出所有的素数,然后线性递推。
如果 R < N ,可知 N! 一定是 R 的倍数,所以我们认为这个结果一定是 0 ,所以写了个特判。真的是这样吗?
有一种特殊情况,N!和 φ(M!) 中有 R 这个因子,M! 也有 R 这个因子,但是 N!φ(M!) 中的 R 的数量和 M! 中的 R 的数量相等,正好抵消掉了。
N!中 R 的数量一定大于等于 M!中 R 的数量。如果 N!和 φ(M!)中的 R 的数量和 M!中的 R的数量相等,那么结果和 R 无关。如果大于,那么直接输出 0 即可。因为大于的情况,结果一定是 R 的倍数,对 R 取余一定是 0
大于的情况容易处理,相等的情况需要再做处理。因为在相等的情况中,结果和 R 无关。但是取余的时候是 R 的倍数会变成 0 ,导致答案不正确。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值