加载中...

第四章 数学知识二

欧拉函数

什么是欧拉函数

欧拉函数ϕ(n)1 - n 中与 n 互质的数的个数

例如:ϕ(6)=2,1 - 6 中与 6 互质的数为 1、5

a,b互质就是gcd(a,b) = 1

如何求解欧拉函数

对于一个数N,可以分解质因数为N=P1k1×P2k2××Pnkn,则ϕ(N)=N×(11P1)×(11P2)××(11Pn)

比如 6=2×3,则ϕ(6)=6×(112)×(113)=2

证明

利用容斥原理

  1. 从1 - N 中 去除其全部质因子P1Pn的所有倍数,那么还剩下S1=NNP1NP2NPn个数
  2. 有的数既是Pi的倍数又是Pj的倍数因此被减了两遍,需要将这一部分加回来,S2=S1+NP1×P2+NP1×P3++NP1×Pn+NP2×P3++NP2×Pn++NPn1×Pn
  3. 有的数是PiPjPk的倍数,在第一步减了三次,在第二步加了三次,相当于没加也没减,因此需要减掉一次,因此S3=S2NPi×Pj×Pk[i,j,k]是1 - n的一组排列

以此类推到第n步,化简就是上边的公式

代码模板

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

!注意每一步计算res×(11i)可能会出现小数,可以转换为resi×(i1)就能保证结果是整数

筛法求欧拉函数

利用质数的线性筛法求1-n的欧拉函数

由于在线性筛法的执行过程中,对于质数会保留,对于合数会用其最小质因子筛掉。所以线性筛法是会访问到所有数的。而根据上面的推导,在遇到每种情况时,我们都能求出欧拉函数

  • 当这个数是质数:ϕ(i)=i1

  • 当这个数是合数:

    某个合数一定是被pj×i` 给删掉的,我们就在删他的时候求他的欧拉函数值

    1. 如果 i % pj == 0 ,那么pj就是i的某个质因数,那么pj×ii的质因数组合完全相同,所以ϕ(pj×i)=pj×ϕ(i)
    2. 如果i % pj != 0,那么pj×i的质因数组合就是在i的质因数组合基础上加了一个pj,所以ϕ(pj×i)=pjϕ(i)×(11pj)=(pj1)×ϕ(i)

代码模

int primes[N], cnt; // primes[]存储所有素数 int euler[N]; // 存储每个数的欧拉函数 bool st[N]; // st[x]存储x是否被筛掉 void get_eulers(int n) { euler[1] = 1; for (int i = 2; i <= n; i ++ ) { if (!st[i]) { primes[cnt ++ ] = i; euler[i] = i - 1; } for (int j = 0; primes[j] <= n / i; j ++ ) { int t = primes[j] * i; st[t] = true; if (i % primes[j] == 0) { euler[t] = euler[i] * primes[j]; break; } euler[t] = euler[i] * (primes[j] - 1); } }

欧拉函数应用

欧拉定理:若a与n互质,那么有aϕ(n) mod n=1

费马定理若a与p互质,p是质数,那么有aϕ(p) mod p =ap1 mod p = 1

证明略

快速幂

可以快速的求出ak mod p 的值,时间复杂度是O(logk),其中a、k、p的范围都是109

核心思路:反复平方法

预处理出:a20 mod p、a21 mod p、a22 mod p、a2log2k mod p 一共
log2k 个数

当求 ak mod p 时利用预处理的这些值组合出ak,即将 ak 拆成 ak=a2x1×a2x2××a2xt=a2x1+2x2++2xt

得到k=2x1+2x2++2xt,其实,就只需要把 k 转化为二进制即可

预处理一共计算出log2k个数,需要计算 log2k 次,将 k 拆成二进制表示,并计算结果,需要 log2k 次,所以总共的时间复杂度就是O(log2k)。其实编写代码时,可以将上面两步合在一起,实际只需要 log2k 次运算,例如45=4(101)2=420×422

代码模板

typedef long long LL; int qmi(int a, int k, int p) { int res = 1; while (k) { if (k & 1) res = (LL)res * a % p; k >>= 1; a = LL(a) * a % p; } return res; }

扩展欧几里得算法

裴蜀定理:对于任意正整数a,b,那么一定存在非零整数x,y,使得ax+by=gcd(a,b)

证明:令 gcd(a,b) = c ,则a一定是c的倍数,b也一定是c的倍数,那么ax+by也一定是c的倍数,那么可以凑出最小的倍数就是1倍,即ax+by=gcd(a,b)

给定a,b如何求解x,y就是扩展欧几里得算法

代码模板

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;

扩展欧几里得算法用来解决这样一个问题,ax+by=m,求x,y,如果m是gcd(a,b)的倍数,则有解,解就是倍数乘以x,y,否则就是无解

此外,还可以解线性同余方程/方程组,例如解axb(mod m),做一下变换就是ax=km+b,即axkm=b,就可以用扩展欧几里得算法解决,878. 线性同余方程

解方程组xa1(mod m1)xa2(mod m2)两两合并x=k1m1+a1=k2m2+a2,做一下变换k1m1k2m2=a2a1,有解的条件是a2a1gcd(m1,m2)的倍数,解出通解是k1+km2dk2+km1d,其中d=gcd(m1,m2),带入原式得x=(k1+km2d)m1+a1=k lcd(m1,m2)+k1m1+a1=km+a,其中m=lcd(m1,m2)a=k1m1+a1,这样就将两个方程合并成了一个方程,然后继续向后合并计算,直到只有一个方程就可以向上面的方式进行1iu

中国剩余定理

有k个两两互质的数m1m2mk,给定线性同余方程组xa1(mod m1)xa2(mod m2)、… 、xak(mod mk),求x

解法:令M=m1×m2××mk

Mi=Mmi,用Mi1表示Mimi 的逆(Mi×Mi11(mod mi)

x=a1×M1×M11+a2×M2×M21++ak×Mk×Mk1


__EOF__

本文作者Chenjq
本文链接https://www.cnblogs.com/chenjq12/p/17115049.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   Chenjq12  阅读(30)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示