数学基础课2_欧拉函数,线性筛,扩欧

本文详细介绍了欧拉函数的定义、性质及计算方法,包括线性筛法和容斥原理推导。此外,还探讨了欧拉定理及其在剩余系、逆元和中国剩余定理中的应用。内容涵盖了费马小定理、裴蜀定理以及扩展欧几里得算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

欧拉函数

ϕ ( n ) \phi(n) ϕ(n) 表示 1 ∼ n 1 \sim n 1n 中与 n n n 互质的数的个数。

N = p 1 α 1 p 2 α 2 p 3 α 3 . . . p k α k N = p_1^{\alpha_1}p_2^{\alpha_2}p_3^{\alpha_3}...p_k^{\alpha_k} N=p1α1p2α2p3α3...pkαk

ϕ ( n ) = N ( 1 − 1 p 1 ) ( 1 − 1 p 2 ) . . . ( 1 − 1 p k ) \phi(n) = N(1-\frac{1}{p_1})(1-\frac{1}{p_2})...(1-\frac{1}{p_k}) ϕ(n)=N(1p11)(1p21)...(1pk1)

利用容斥原理推导。

有一个实现的细节。 N ∗ ( 1 − 1 n ) = N ∗ ( n − 1 n ) = N / n ∗ ( n − 1 ) N*(1-\frac{1}{n}) = N*(\frac{n-1}{n}) = N/n*(n-1) N(1n1)=N(nn1)=N/n(n1)

#include <iostream>
using namespace std;
int phi(int x){
    int res = x;
    for (int i = 2; i <= x / i; i ++ )
        if (x % i == 0){
            res = res / i * (i - 1);
            while (x % i == 0) x /= i;
        }
    if (x > 1) res = res / x * (x - 1);
    return res;
}
int main(){
    int n;
    cin >> n;
    while (n -- ){
        int x;
        cin >> x;
        cout << phi(x) << endl;
    }
    return 0;
}
1. 用公式求N个数的欧拉函数 O ( N k ) O(N \sqrt{k}) O(Nk )
#include<iostream>
using namespace std;
const int N=1e6+10;
int p[N],cnt[N];

long long f(int n){
    long long res=n;
    for(int i=2;i<=n/i;i++){
        if(n%i==0){
            res=res/i*(i-1);
            while(n%i==0){
                n/=i;
            }
        }
    }
    if(n>1)
	    res=res/n*(n-1);
    return res;
}
int main(){
    int n;cin>>n;
    while(n--){
        int a;cin>>a;
        cout<<f(a)<<endl;;
    }
    return 0;
}
2.线性筛 1 ∼ n 1\sim n 1n 中每一个数的欧拉函数 O ( n ) O(n) O(n)

线性筛可以求很多数论函数

i i i 是质数的时候, p h i ( i ) = i − 1 phi(i) = i-1 phi(i)=i1

i i i 不是质数的时候:

  1. i % p r e [ j ] = = 0 i \%pre[j] == 0 i%pre[j]==0 p r e [ j ] 是 i ∗ p r e [ j ] 的 最 小 质 因 子 pre[j] 是 i*pre[j] 的最小质因子 pre[j]ipre[j],又因为 i i i 中包含质因子 p r e [ j ] pre[j] pre[j]

p h i ( n ) phi(n) phi(n) 只和 n n n 分解出的质数有关,和质数的指数无关,所以 p h i [ i ∗ p r e [ j ] ] = p r e [ j ] ∗ p h i [ i ] phi[i*pre[j]] = pre[j] *phi[i] phi[ipre[j]]=pre[j]phi[i]

  1. i % p r e [ j ] ! = 0 i \%pre[j] !=0 i%pre[j]!=0 p r e [ j ] pre[j] pre[j] 是比 i ∗ p r e [ j ] i*pre[j] ipre[j] 的最小质因子还要小的质因子,所以:

p h i ( i ∗ p r e [ j ] ) = p h i ( i ) ∗ p r e [ j ] ∗ ( 1 − 1 p r e [ j ] ) = p h i [ i ] ∗ ( p r e [ j ] − 1 ) phi(i*pre[j]) = phi(i)*pre[j]*(1-\frac{1}{pre[j]}) = phi[i]*(pre[j]-1) phi(ipre[j])=phi(i)pre[j](1pre[j]1)=phi[i](pre[j]1)

int pre[N],cnt,n;
int phi[N];//求1~n中每个数的欧拉函数 
bool st[N];

void get_euler(int n){
	phi[1]=1;
	for(int i=2;i<=n;i++){
		if(!st[i]){
			pre[cnt++]=i;	
			phi[i]=i-1;
		}
		for(int j=0;pre[j]<=n/i;j++){
			st[i*pre[j]]=1;
			if(i%pre[j]==0){
				phi[i*pre[j]] = pre[j] * phi[i];
				break;	
			}
			phi[i*pre[j]] = phi[i] * (pre[j]-1);
		}
	}
}

欧拉函数的应用

欧拉定理:若 a a a n n n 互质,则 a ϕ ( n ) ≡ 1 ( m o d   n ) a^{\phi(n)} \equiv 1 (mod \ n) aϕ(n)1(mod n)

剩余系?

证明欧拉定理:

前置知识:a和b互质,c和b互质,a * c和b互质

$1\sim n $ 中 有 p h i ( n ) phi(n) phi(n) 个数和 n n n 互质, a 1 , a 2 , . . . , a p h i ( n ) a_1,a_2,...,a_{phi(n)} a1,a2,...,aphi(n)

所以的 a i a_i ai a a a 有: a 1 ∗ a , a 2 ∗ a , . . . , a p h i ( n ) ∗ a a_1*a,a_2*a,...,a_{phi(n)}*a a1a,a2a,...,aphi(n)a ,这些数也和 n n n 互质。

又因为这些数两两不同,且与 n n n 互质的个数只有 p h i ( n ) phi(n) phi(n) 个,所以上边的两组是在模 n n n 意义下是相等的。

​ 证明为什么第二组数在模 n n n 的意义下两两不同。

​ 反证:假设 a i , a j a_i,a_j ai,aj 在模 n n n 的意义下是相等的有:

a ∗ a i ≡ a ∗ a j ( m o d   n ) a*a_i \equiv a*a_j (mod \ n) aaiaaj(mod n)

a ∗ ( a i − a j ) ≡ 0 ( m o d   n ) a*(a_i-a_j) \equiv 0 (mod \ n) a(aiaj)0(mod n)

又因为 a a a n n n 是互质的(大条件),所以有 a i − a j ≡ 0 ( m o d   n ) a_i-a_j \equiv 0 (mod \ n) aiaj0(mod n) 与1式子矛盾,得证。

#####欧拉定理的特例:费马定理:当 n n n 是质数,且 a a a n n n 互质的时候 a n − 1 ≡ 1 ( m o d   n ) a^{n-1} \equiv 1 (mod \ n) an11(mod n)

两组数的乘积在模 n n n 的意义下是相等的。乘起来化简就证明了欧拉定理。

欧拉定理的推论

若正整数 a a a , n n n 互质,则对于任意正整数 b b b , 有 a b ≡ a b   m o d   ϕ ( n )   m o d   ( n ) a^b \equiv a^{b \ mod \ \phi(n) }\ mod \ (n) abab mod ϕ(n) mod (n)

蓝书上给出了精简的证明:

b = q ∗ ( ϕ ( n ) ) + r b = q*(\phi(n))+r b=q(ϕ(n))+r , 0 ≤ r < ϕ ( n ) 0 \leq r < \phi(n) 0r<ϕ(n) ,有:

a b ≡ a q ∗ ( ϕ ( n ) ) + r ≡ a ϕ ( n ) q ∗ a r ≡ 1 q ∗ a r ≡ a r ≡ a b   m o d   ϕ ( n )   m o d   ( n ) a^b \equiv a^{q*(\phi(n))+r} \equiv a^{\phi(n)^{q}}*a^r \equiv 1^q*a^r\equiv a^{r} \equiv a^{b \ mod\ \phi(n)}\ mod \ (n) abaq(ϕ(n))+raϕ(n)qar1qararab mod ϕ(n) mod (n)

特别的,如果 a a a n n n 不互质,当 b > ϕ ( n ) b> \phi(n) b>ϕ(n) 时,有 a b ≡ a b   m o d   ϕ ( n ) + ϕ ( n )   m o d   ( n ) a^b \equiv a^{b \ mod\ \phi(n) + \phi(n)} \ mod \ (n) abab mod ϕ(n)+ϕ(n) mod (n)

逆元

b b b, m m m 互质, b ∣ a b|a ba a b ≡ a ∗ x ( m o d   n ) \frac{a}{b} \equiv a*x (mod \ n) baax(mod n)

a b ≡ a ∗ b − 1 ( m o d   n ) \frac{a}{b} \equiv a*b^{-1} (mod \ n) baab1(mod n)

x x x 叫做 b b b n n n 的乘法逆元。记作 b − 1 b^{-1} b1(是个整数)

证明:

发现了盲点! 费马小定理有两种表述方式:

n n n 是质数,且 a a a n n n 互质的时候 a n − 1 ≡ 1   ( m o d   n ) a^{n-1} \equiv 1 \ (mod \ n) an11 (mod n)

n n n 是质数,则对于任意整数 a a a , 有 a n ≡ a   ( m o d   n ) a^{n} \equiv a \ (mod \ n) ana (mod n)

原理很简单,当 a a a n n n 互质的时候, a % n ! = 0 a\%n!=0 a%n!=0 , 同于式两边就是消去 a a a 了。

利用 费马定理

a ∗ x ≡ 1 ( m o d   p ) a ∗ x ≡ a p − 1 ( m o d   p ) x ≡ a p − 2 ( m o d   p ) a*x \equiv 1 (mod\ p)\\ a*x \equiv a^{p-1} (mod \ p)\\ x \equiv a^{p-2} (mod \ p) ax1(mod p)axap1(mod p)xap2(mod p)

无解的情况:如果 a a a p p p 的倍数,那么 p ∣ a ∗ x p|a*x pax 有, a ∗ x   m o d   p = 0 a*x \ mod\ p =0 ax mod p=0,原式不成立。


裴蜀定理

​ 对于任意正整数 a , b a,b a,b ,一定存在整数 x , y x,y x,y ,使得: a x + b y = g c d ( a , b ) ax+by = gcd(a,b) ax+by=gcd(a,b)

​ 可以发现 ( a , b ) (a,b) (a,b) a 和 b a和b ab 能凑出来的最小的正整数。

(a-1)*(b-1)-1 是 a和b 不能凑出来的最大的正整数。

裴蜀定理的证明是通过扩展欧几里得算法得到的。

扩展欧几里得算法
#include<iostream>
#include<algorithm>
using namespace std;

int extgcd(int a,int b,int &x,int &y)// 返回的是gcd(a,b)
{
    if(b==0){
        // a*x+b*y=gcd(a,b)
        // a + 0 = gcd(a,0) = a
        x=1,y=0;
        return a;
    }
    /*
    递归求解的,  b*y+(a%b)*x=gcd(b,a%b)=gcd(a,b)
	化简得到
	x * a +[y-a/b*x] b = gcd(a,b)
	a的系数还是x;
	y-=(a/b*x);
    */
    int d=extgcd(b,a%b,y,x);//记得翻转 x,y
    y-=a/b*x;
    return d;
}

int main()
{
    int n;cin>>n;
    while(n--)
    {
        int a,b,x,y;
        scanf("%d%d",&a,&b);
        int t=extgcd(a,b,x,y);
        printf("%d %d\n",x,y);
    }
    return 0;
}

扩展欧几里得的通解。

a x 0 + b y 0 = d x = x 0 − b d k , k ∈ z y = y 0 + a d k ax_0+by_0=d\\ x = x_0-\frac{b}{d}k,k\in z\\ y = y_0+\frac{a}{d}k ax0+by0=dx=x0dbk,kzy=y0+dak

扩欧应用,求解线性同余方程

a x ≡ b   ( m o d   m ) ax \equiv b \ (mod \ m) axb (mod m)

a x − m y = b ax-my=b axmy=b , 方程有解的充要条件 g c d ( a , m ) ∣ b gcd(a,m)|b gcd(a,m)b

#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
int exgcd(int a, int b, int &x, int &y)
{
    if (!b){
        x = 1, y = 0;
        return a;
    }
    int d = exgcd(b, a % b, y, x);
    y -= a / b * x;
    return d;
}


int main()
{
    int n;
    scanf("%d", &n);
    while (n -- )
    {
        int a, b, m;
        scanf("%d%d%d", &a, &b, &m);
        int x, y;
        int d = exgcd(a, m, x, y);
        if (b % d) puts("impossible");
        else printf("%d\n", (LL)b / d * x % m);
    }
    return 0;
}

在用扩展欧几里得算法求逆元的基础上的 中国剩余定理

m 1 , m 2 , . . . , m n m_1,m_2,...,m_n m1,m2,...,mn 是两两互质 的整数, M = ∏ i = 1 n m i M = \prod_{i=1}^{n} m_i M=i=1nmi M i = M m i M_i = \frac{M}{m_i} Mi=miM

对于 n n n 个整数 a 1 , a 2 , . . . , a n a_1,a_2,...,a_n a1,a2,...,an 方程组。
x ≡ a 1 ( m o d   m 1 ) x ≡ a 2 ( m o d   m 2 ) . . . x ≡ a n ( m o d   m n ) x \equiv a_1 (mod \ m_1)\\ x \equiv a_2 (mod \ m_2)\\ ...\\ x \equiv a_n (mod \ m_n) xa1(mod m1)xa2(mod m2)...xan(mod mn)
构造出一组解: x = a 1 ∗ M 1 ∗ M 1 − 1 + a 2 ∗ M 2 ∗ M 2 − 1 + . . . + a n ∗ M n ∗ M n − 1 x = a_1 * M_1*M_1^{-1}+a_2 * M_2*M_2^{-1}+...+a_n * M_n*M_n^{-1} x=a1M1M11+a2M2M21+...+anMnMn1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值