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

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

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

N=p1α1p2α2p3α3...pkαkN = 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−1p1)(1−1p2)...(1−1pk)\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−1n)=N∗(n−1n)=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(Nk)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∼n1\sim n1n 中每一个数的欧拉函数 O(n)O(n)O(n)

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

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

iii 不是质数的时候:

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

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

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

phi(i∗pre[j])=phi(i)∗pre[j]∗(1−1pre[j])=phi[i]∗(pre[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);
		}
	}
}

欧拉函数的应用

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

剩余系?

证明欧拉定理:

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

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

所以的 aia_iaiaaa 有:a1∗a,a2∗a,...,aphi(n)∗aa_1*a,a_2*a,...,a_{phi(n)}*aa1a,a2a,...,aphi(n)a ,这些数也和 nnn 互质。

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

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

​ 反证:假设 ai,aja_i,a_jai,aj 在模 nnn 的意义下是相等的有:

a∗ai≡a∗aj(mod n)a*a_i \equiv a*a_j (mod \ n)aaiaaj(mod n)

a∗(ai−aj)≡0(mod n)a*(a_i-a_j) \equiv 0 (mod \ n)a(aiaj)0(mod n)

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

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

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

欧拉定理的推论

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

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

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

ab≡aq∗(ϕ(n))+r≡aϕ(n)q∗ar≡1q∗ar≡ar≡ab mod ϕ(n) mod (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)

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

逆元

bbb, mmm 互质,b∣ab|abaab≡a∗x(mod n)\frac{a}{b} \equiv a*x (mod \ n)baax(mod n)

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

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

证明:

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

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

nnn 是质数,则对于任意整数 aaa , 有 an≡a (mod n)a^{n} \equiv a \ (mod \ n)ana (mod n)

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

利用 费马定理

a∗x≡1(mod p)a∗x≡ap−1(mod p)x≡ap−2(mod 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)

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


裴蜀定理

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

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

(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;
}

扩展欧几里得的通解。

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

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

ax≡b (mod m)ax \equiv b \ (mod \ m)axb (mod m)

ax−my=bax-my=baxmy=b , 方程有解的充要条件 gcd(a,m)∣bgcd(a,m)|bgcd(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;
}

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

m1,m2,...,mnm_1,m_2,...,m_nm1,m2,...,mn 是两两互质 的整数,M=∏i=1nmiM = \prod_{i=1}^{n} m_iM=i=1nmiMi=MmiM_i = \frac{M}{m_i}Mi=miM

对于 nnn 个整数 a1,a2,...,ana_1,a_2,...,a_na1,a2,...,an 方程组。
x≡a1(mod m1)x≡a2(mod m2)...x≡an(mod mn) 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=a1∗M1∗M1−1+a2∗M2∗M2−1+...+an∗Mn∗Mn−1x = 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

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值