[C++]数论(二)

2 篇文章 0 订阅

往期回顾

数论(一)

裴蜀定理

内容

裴蜀定理是指方程 a x + b y = m ax + by = m ax+by=m当且仅当m是a和b的最大公因数d的倍数时,方程有整数解
特别的,只有a和b互质时, a x + b y = 1 ax + by = 1 ax+by=1才有整数解

证明

设存在 x , y x,y x,y,满足 a x + b y ax + by ax+by为正数最小值 d d d。任选 m , n m,n m,n不等于 x , y x,y x,y,此时 a m + b n am + bn am+bn e e e,则 e ≥ d e≥d ed
e = p × d + r e=p \times d+r e=p×d+r p p p为商, r r r是余数),则 r < d r<d rd
那么 r = e − p × d = a m + b n − p × ( a x + b y ) = ( m − p x ) × a + ( n − p y ) × b r=e-p \times d=am+bn-p \times (ax+by)=(m-px) \times a+(n-py)\times b r=ep×d=am+bnp×(ax+by)=(mpx)×a+(npy)×b
则有 m − p x m-px mpx n − p y n-py npy满足比d更小的值 r r r r r r只能为0
所以 e e e d d d的倍数
g c d ( a , b ) = l , a = s l , b = t l gcd(a,b)=l,a=sl,b=tl gcd(a,b)=la=slb=tl,则 d = l ( s x + t y ) d=l(sx+ty) d=l(sx+ty),所以 d d d一定是 g c d ( a , b ) gcd(a,b) gcd(a,b)的倍数
综上可知, d d d g c d ( a , b ) gcd(a,b) gcd(a,b)的倍数, e e e d d d的倍数

构造

构造有很多,而扩展欧几里得算法的解就是其中之一。
详情看数论(一),这里不再构造

欧拉定理

欧拉函数

欧拉函数,即 φ ( n ) φ(n) φ(n),指1~ n n n中与 n n n互质的数的个数

欧拉函数的计算

φ ( 1 ) = 1 φ(1)=1 φ(1)=1
如果 i i i是质数,那么 φ ( i ) = i − 1 φ(i)=i-1 φ(i)=i1
如果 i i i是合数,那么设 i = ∏ i = 1 m p i k i i=\prod^{m}_{i=1}p_i^{k_i} i=i=1mpiki p i p_i pi为质数,则 φ ( i ) = n × ∏ i = 1 m p i − 1 p i φ(i)=n\times \prod^{m}_{i=1} \frac{p_i-1}{p_i} φ(i)=n×i=1mpipi1
如果只求一个数的欧拉函数,可以在分解质因数中求
如果求线性的欧拉函数,则可以在线性筛中求

欧拉定理

g c d ( a , m ) = 1 gcd(a,m)=1 gcd(a,m)=1,那么 a φ ( m ) ≡ 1 ( m o d    m ) a^{φ(m)} \equiv1 (\mod m) aφ(m)1(modm)

乘法逆元

我们知道, a × a − 1 ≡ 1 ( m o d    b ) a\times a^{-1}\equiv 1(\mod b) a×a11(modb)
那么如果给定 a , b a,b a,b,怎么求 x = a − 1 x=a^{-1} x=a1

扩展欧几里得算法求逆元

我们知道,扩展欧几里得算法求的是 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)的解
这和乘法逆元又有什么关系呢?
我们先来看看条件吧。
a x ≡ 1 ( m o d    b ) ax \equiv1(\mod b) ax1(modb)一定有解,说明了 a x + b y = g c d ( a , b ) ≡ 1 ( m o d    b ) ax+by=gcd(a,b)\equiv 1(\mod b) ax+by=gcd(a,b)1(modb)
1 ≤ g c d ( a , b ) ≤ b 1 \le gcd(a,b) \le b 1gcd(a,b)b,因此 g c d ( a , b ) = 1 gcd(a,b)=1 gcd(a,b)=1
因此,我们用扩展欧几里得算法可以求出 a x + b y = 1 ax+by=1 ax+by=1的解
在这种情况下,显然 a x ≡ 1 ( m o d    b ) ax \equiv1(\mod b) ax1(modb)
但别忘了现在的 x x x可能不是正整数,也不一定是最小的解,因此我们要的答案是 ( x % b + b ) % b (x\%b+b)\%b (x%b+b)%b
懂了吗?
奉上代码一份:

#include<iostream>
using namespace std;
long long x,y;
void gcd(long long a,long long b){
	if(!b){
		x=1,y=0;
		return ;
	}
	gcd(b,a%b);
	long long t=x;
	x=y,y=t-a/b*y; 
}
int main(){
	long long a,b;
	cin>>a>>b;
	gcd(a,b);
	x=(x%b+b)%b;
	cout<<x;
	return 0;
}

噢,对了,大家还可以顺便把这题给切了,刷个绿题谁不愿意呢?

欧拉定理求逆元

知道我这次为什么必须要讲欧拉定理了吧。
As we all know, a φ ( b ) ≡ 1 ( m o d    b ) a^{φ(b)} \equiv1 (\mod b) aφ(b)1(modb)
∴ a × a φ ( b ) − 1 ≡ 1 ( m o d    b ) ∴a \times a^{φ(b)-1} \equiv 1(\mod b) a×aφ(b)11(modb)
因此,我们要求的乘法逆元就是 a φ ( b ) − 1 % b a^{φ(b)-1} \% b aφ(b)1%b
至于怎么求,快速幂嘛,对吧,反正我也懒得写了嘿嘿
当然如果 b b b是质数,我们用费马小定理也是得出一样的结论的

线性求逆元

如果要求1~n的逆元了,怎么样才能最快?
我想,最缓(xun)慢(su)的做法就是暴力了。
我们可以来找找逆元之间的关系
⌊ p a ⌋ × a = p − ( p % a ) \lfloor \frac{p}{a} \rfloor\times a=p-(p\%a) ap×a=p(p%a)
⌊ p a ⌋ × a ≡ − ( p % a ) ( m o d    p ) \lfloor \frac{p}{a} \rfloor\times a\equiv -(p\%a) (\mod p) ap×a(p%a)(modp)
a ≡ − ( p % a ) ⌊ p a ⌋ ( m o d    p ) a\equiv\frac{-(p\%a)}{\lfloor \frac{p}{a} \rfloor} (\mod p) aap(p%a)(modp)
a − 1 ≡ ⌊ p a ⌋ − ( p % a ) ( m o d    p ) a^{-1}\equiv\frac{\lfloor \frac{p}{a} \rfloor}{-(p\%a)} (\mod p) a1(p%a)ap(modp)
a − 1 ≡ − ⌊ p a ⌋ × ( p % a ) − 1 ( m o d    p ) a^{-1}\equiv -\lfloor \frac{p}{a} \rfloor\times (p\%a)^{-1} (\mod p) a1ap×(p%a)1(modp)
所以我们就可以通过这个来计算线性上的逆元了

inv[1]=1;
for(int i=2;i<=n;i++){
	inv[i]=(long long)(b-b/i)*inv[b%i]%b
}

今天要不就到这吧。

  • 8
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值