欧拉函数笔记

一、积性函数

1 定义

对于两个互质的正整数 n , m n,m n,m ,如果满足:
f ( m n ) = f ( m ) f ( n ) f(mn)=f(m)f(n) f(mn)=f(m)f(n)
那么 f ( x ) f(x) f(x) 这个函数就是一个积性函数。
如果对于任意两个正整数 n , m n,m n,m ,满足:
f ( m n ) = f ( m ) f ( n ) f(mn)=f(m)f(n) f(mn)=f(m)f(n)
那么 f ( x ) f(x) f(x) 就是一个完全积性函数。

2 积性函数举例

  1. 常数函数 f ( n ) = 1 f(n)=1 f(n)=1
  2. 单位函数 f ( n ) = [ n = 1 ] f(n)=[n=1] f(n)=[n=1]
    证明: f ( n ) ⋅ f ( m ) = { 0   e l s e 1   n = 1 , m = 1 = f ( n ) ( m ) f(n)\cdot f(m)=\{^{1\ n=1,m=1}_{0\ else}=f(n)(m) f(n)f(m)={0 else1 n=1,m=1=f(n)(m)
  3. 除数函数 σ k ( n ) = ∑ d ∣ n d k \sigma_k(n)=\sum_{d\mid n}d^k σk(n)=dndk
  4. 欧拉函数 φ ( n ) = ∑ j = 1 n [ g c d ( i , n ) = 1 ] \varphi(n)=\sum^n_{j=1}[gcd(i,n)=1] φ(n)=j=1n[gcd(i,n)=1],又能写成 φ ( n ) = n ( 1 − 1 p 1 ) ( 1 − 1 p 2 ) … ( 1 − 1 p n ) \varphi(n)=n(1-\frac{1}{p_1})(1-\frac{1}{p_2})\ldots(1-\frac{1}{p_n}) φ(n)=n(1p11)(1p21)(1pn1),用来求比 n 小且与 n 互质的正整数个数。
  5. 莫比乌斯函数 μ ( n ) \mu(n) μ(n)
    性质:
    ∑ d ∣ n μ ( d ) = [ n = 1 ] = { 0   e l s e 1   n = 1 \sum_{d|n}\mu(d)=[n=1]=\lbrace^{1\ n=1}_{0\ else} dnμ(d)=[n=1]={0 else1 n=1

二、欧拉函数

以下有几个性质:(p均指质数)

  1. n n n 是质数, φ ( n ) = n − 1 \varphi(n)=n-1 φ(n)=n1
  2. n = p n=p n=p φ ( n ) = p k − k k − 1 \varphi(n)=p^k-k^{k-1} φ(n)=pkkk1
  3. n n n 是奇数, φ ( 2 n ) = φ ( n ) \varphi(2n)=\varphi(n) φ(2n)=φ(n)
  4. ∑ d ∣ n φ = n \sum_{d|n}\varphi=n dnφ=n

三、欧拉定理

若a与m互质,则:
a ϕ ( m ) ≡ 1 ( m o d   m ) a^{\phi(m)}\equiv 1(mod\ m) aϕ(m)1(mod m)
这就是欧拉定理。欧拉定理、威尔逊定理、费马小定理、中国剩余定理并称为数论四大定理

如果p是质数。那么:
a p − 1 ≡ 1 ( m o d   p ) a^{p-1}\equiv 1(mod\ p) ap11(mod p)
刚好我们发现从欧拉定理变成了费马小定理。也就是说,费马小定理是欧拉定理的一个特例。

而当 a a a p p p 互质时:
a b ≡ a b   m o d   ϕ ( p ) ( m o d   p ) a^b\equiv a^{b\ mod\ \phi(p)}(mod\ p) abab mod ϕ(p)(mod p)
实际上,这是扩展欧拉定理的一部分,也叫欧拉降幂:
a b ≡ { a b                                      b < ϕ ( m ) a ( b   m o d   ϕ ( m ) ) + ϕ ( m )              b ≥ ϕ ( m ) m o d    m a^b\equiv\left\{ \begin{matrix} a^{b}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~b<\phi(m)\\ a^{(b~mod~\phi(m))+\phi(m)} ~~~~~~~~~~~~b\ge \phi(m) \end{matrix}\right. mod ~~m ab{ab                                    b<ϕ(m)a(b mod ϕ(m))+ϕ(m)            bϕ(m)mod  m

四、线性筛

1 简介

线性筛(又名欧拉筛),是一种用于找出一定范围内素数的算法。顾名思义,它能够在 O ( n ) O(n) O(n) 的时间内完成任务。
线性筛的核心思想是每个合数只会被它的最小质因子筛去一次。我们从小到大枚举每个数,如果这个数是质数,就将它的倍数标记为非质数。同时,每个合数只会被它的最小质因子标记,避免了重复标记。

2 练习

2.1 题目描述

给定一个范围 [ 1 , n ] [1,n] [1,n] ,有 q q q 词询问,每次输出第 k k k 小的数。

2.2 代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
bool vis[100000002];
int prime[10000002],cnt;
int n,q;
void sieve(ll n){
	vis[1]=1;
	for(int i=2;i<=n;i++){
		if(!vis[i]){
			prime[++cnt]=i;
		}
		for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
			vis[i*prime[j]]=1;
			if(i%prime[j]==0){
				break;
			}
		}
	}
}
int main(){
    scanf("%d%d",&n,&q);
    sieve(n);
    while(q--){
    	int k;
    	scanf("%d",&k);
		printf("%d\n",prime[k]);
	}
    return 0;
}

五、欧拉函数实践

1 求欧拉函数

1.1 题目描述

输入 n n n ,请输出 φ ( n ) \varphi(n) φ(n) 的值

1.2 思路

a n s ans ans 等于 n n n ,代表了小于 n n n 的所有正整数。当我们发现 n n n 可以被一个数 i i i 整除时,我们需要从 a n s ans ans 中减去那些也能被 i i i 整除的数。这些数的数量可以通过 a n s i \frac{ans}{i} ians 来计算。

1.3 代码

#include<bits/stdc++.h>
#define ll long long
#define bug printf("---OK---")
#define pa printf("A: ")
#define pr printf("\n")
#define pi acos(-1.0)
using namespace std;
ll n;
ll phi(ll n){
    ll ans=n;
    for(int i=2;i<=sqrt(n);i++){
        if(n%i==0){
            while(n%i==0){//当n能被i整除时,不断地除以i
                n/=i;
            }
            ans-=ans/i;//从结果中减去ans/i
        }
    }
    if(n>1){//如果n大于1,说明n是一个大于sqrt(n)的质数
        ans-=ans/n;//从结果中减去ans/n
    }
    return ans;
}
int main(){
	while(scanf("%lld",&n)&&n!=0){
		printf("%lld\n",phi(n));
	}
    return 0;
}

2 Farey数列

1.1 题目描述

对于一个大于 1 1 1 的整数 n n n ,定义Farey序列 F n F_n Fn 为一个分数集合 { a / b , 0 < a < b ≤ n \{{a/b},0<a<b\leq n {a/b,0<a<bn gcd ⁡ ( a , b ) = 1 } \gcd(a,b)=1\} gcd(a,b)=1}
例如,前几项为
F 2 = { 1 / 2 } F_2=\{1/2\} F2={1/2}
F 3 = { 1 / 3 , 1 / 2 , 2 / 3 } F_3=\{1/3,1/2,2/3\} F3={1/3,1/2,2/3}
F 4 = { 1 / 4 , 1 / 3 , 1 / 2 , 2 / 3 , 3 / 4 } F_4=\{1/4,1/3,1/2,2/3,3/4\} F4={1/4,1/3,1/2,2/3,3/4}
F 5 = { 1 / 5 , 1 / 4 , 1 / 3 , 2 / 5 , 1 / 2 , 3 / 5 , 2 / 3 , 3 / 4 , 4 / 5 } F_5=\{1/5,1/4,1/3,2/5,1/2,3/5,2/3,3/4,4/5\} F5={1/5,1/4,1/3,2/5,1/2,3/5,2/3,3/4,4/5}
每次给定 n n n ,求 F n F_n Fn 中分数的个数。

1.2 思路

分数没什么用,实际上是求欧拉函数前 n n n 项的和。

1.3 代码

#include<bits/stdc++.h>
#define ll long long
#define bug printf("---OK---")
#define pa printf("A: ")
#define pr printf("\n")
#define pi acos(-1.0)
using namespace std;
const ll N=1e6+2;
ll t,x;
ll phi[N],prime[N],tot;
void le(int n){//线性筛的同时求欧拉函数,降低时间复杂度
    phi[1]=phi[0]=0;
    for(int i=2;i<=n;i++){
        if(!phi[i]){
        	phi[i]=i-1;
			prime[++tot]=i;
		}
        for(int j=1;j<=tot&&i*prime[j]<=n;j++){
            if(i%prime[j]==0){
                phi[i*prime[j]]=phi[i]*prime[j];
                break;
            }
			else{
				phi[i*prime[j]]=phi[i]*(prime[j]-1);
			}
        }
    }
}
int main(){
	le(N);//预处理
	for(int i=1;i<=N;i++){
		phi[i]+=phi[i-1];//相加
	}
	while(scanf("%lld",&x)&&x!=0){
		printf("%lld",phi[x]);pr;
	}
    return 0;
}

3 【模板】欧拉降幂

3.1 题目描述

求: a b ( m o d   m ) a^b(mod\ m) ab(mod m)
提示: b ≤ 1 0 200000000 b\le10^{200000000} b10200000000

3.2 思路

由于b太大了,需要用欧拉降幂的公式。使用字符串处理即可。

3.3 代码

#include<bits/stdc++.h>
#define ll long long
#define bug printf("---OK---")
#define pa printf("A: ")
#define pr printf("\n")
#define pi acos(-1.0)
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
ll a,m;
string s;
ll qpow(ll x,ll y){
	ll ans=1;
	while(y>0){
		if(y&1==1){
			ans=(ans*x)%m;
		}
		x=(x*x)%m;
		y>>=1;
	}
	return ans;
}
ll oul(ll n){
    ll ans=n;
    for(ll i=2;i<=sqrt(n);i++){
        if(n%i==0){
            while(n%i==0){
                n/=i;
            }
            ans-=ans/i;
        }
    }
    if(n>1){
        ans-=ans/n;
    }
    return ans;
}
ll downp(ll phi){
	ll len=s.size();
	ll b=0;
	bool flag=0;
	for(ll i=0;i<len;i++){
		b=b*10+s[i]-'0';
		if(b>=phi){
			b%=phi;
			flag=1;
		}
	}
	if(flag==1){
		b+=phi;
	}
	return b;
}
int main(){
	cin>>a>>m>>s;
	cout<<qpow(a,downp(oul(m)));
	return 0;
}
  • 18
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值