数论基础(质数筛法、同余、快速幂、gcd、裴蜀定理)

整除、同余

a a a, b b b为整数, a ≠ 0 a\neq 0 a=0 如果存在一个整数q,使得 a × q = b a\times q=b a×q=b,则 b b b能被 a a a整除,记为 a ∣ b a\mid b ab,且称 b b b a a a的倍数, a a a b b b的因子。

整除的几个性质:

  1. 传递性:如果 a ∣ b a|b ab b ∣ c b|c bc,则 a ∣ c a|c ac
  2. a|b且a|c等价于对于任意的整数x,y,有a|(bx+cy)
  3. 设m不为0,则a|b等价于ma|mb
  4. 设整数x,y满足下式:ax+by=1,且a|n,b|n,那么(ab)|n
  5. 若b=q*d+c,那么d|b的充要条件是d|c.

同余的几个性质:

  1. 同加性:若 a ≡ b ( m o d p ) , a\equiv b \pmod p, ab(modp), a + c ≡ b + c ( m o d p ) a+c \equiv b+c \pmod p a+cb+c(modp)
  2. 同减性:若 a ≡ b ( m o d p ) , a\equiv b \pmod p, ab(modp), a − c ≡ b − c ( m o d p ) a-c \equiv b-c \pmod p acbc(modp)
  3. 同乘性:若 a ≡ b ( m o d p ) , a\equiv b \pmod p, ab(modp), a × c ≡ b × c ( m o d p ) a \times c \equiv b\times c \pmod p a×cb×c(modp)
  4. 同除性:若 a ≡ b ( m o d p ) a\equiv b \pmod p ab(modp),且 c ∣ a , c ∣ b , ( c , p ) = 1 c \mid a,c\mid b,(c,p)=1 ca,cb,(c,p)=1,则 a / c ≡ b / c ( m o d p ) a/c \equiv b/c \pmod p a/cb/c(modp)
  5. 同幂性:若 a ≡ b ( m o d p ) , c > 0 , a\equiv b \pmod p,c>0, ab(modp),c>0, a c ≡ b c ( m o d p ) a^c \equiv b^c \pmod p acbc(modp)
  6. a % p = x , a % q = x a\%p=x,a\%q=x a%p=x,a%q=x,且 p , q p,q p,q互质,则 a % ( p ∗ q ) = x a\%(p*q)=x a%(pq)=x

数论小常识:

  1. 2 2 2能整除 a a a的最末位,则 2 ∣ a 2|a 2a
  2. 4 4 4能整除 a a a的末两位,则 4 ∣ a 4|a 4a
  3. 8 8 8能整除 a a a的末三位,则 8 ∣ a 8|a 8a
  4. 3 3 3能整除 a a a的各位数字之和,则 3 ∣ a 3|a 3a
  5. 9 9 9能整除 a a a的各位数字之和,则 9 ∣ a 9|a 9a
  6. 11 11 11能整除 a a a的偶数位数字之和与奇数位数字之和的差,则 11 ∣ a 11|a 11a
  7. 能被 7 7 7 11 11 11 13 13 13整除的数的特征是:这个数的末三位与末三位以前的数字所组成数之差能被 7 7 7 11 11 11 13 13 13整除。

模运算

对于整数a,b,其中b不为0,求a除以b的余数,称为a模b,记为 a % b a\%b a%b.
模运算的性质:

  1. 分配率:模运算对加、减、乘具有分配率
    ( a + b ) % c = ( a % c + b % c ) % c (a+b)\%c=(a\%c+b\%c)\%c (a+b)%c=(a%c+b%c)%c
    ( a − b ) % c = ( a % c − b % c ) % c (a-b)\%c=(a\%c-b\%c)\%c (ab)%c=(a%cb%c)%c
    ( a ∗ b ) % c = ( a % c ∗ b % c ) % c (a*b)\%c=(a\%c*b\%c)\%c (ab)%c=(a%cb%c)%c
    ( a b ) % c = ( a % c ) b % c (a^b)\%c=(a\%c)^b\%c (ab)%c=(a%c)b%c
  2. 放缩性
    如果 a % b = c , d ≠ 0 a\%b=c,d \neq 0 a%b=c,d=0,则有 ( a ∗ d ) % ( b ∗ d ) = c ∗ d (a*d)\%(b*d)=c*d (ad)%(bd)=cd;
    如果 a % b = c , d ∣ a , d ∣ b a\%b=c,d\mid a,d \mid b a%b=c,da,db,则 ( a / d ) % ( b / d ) = ( c / d ) (a/d)\%(b/d)=(c/d) (a/d)%(b/d)=(c/d).
    根据放缩性,则除法取余有这个式子:
    a / b % c = a % ( b ∗ c ) / b a/b\%c=a\%(b*c)/b a/b%c=a%(bc)/b

快速幂取模

已知 a , b , p a,b,p a,b,p为整数,求 a b % p a^b\%p ab%p的结果。
可以用二进制倍增的思想,快速求幂。
a的b次方,可以看做是b个a相乘,b可以拆成2的幂的和,于是可以求出a的1次方,a的2次方,a的4次方, … \dots ,只要b的二进制的从右数第k位为1,则a的 2 k 2^k 2k方乘到结果里即可。
代码非常短小精悍:

LL ksm(LL a,LL b,LL p)
{
	LL res=1;
	while(b)
	{
		if(b&1)res=res*a%p;
		a=a*a%p;
		b>>=1;
	}
	return res;
}

类似的,还有快速乘取模,也是一样运用2进制倍增的思想。
例:求 a ∗ b % p a*b\%p ab%p的结果,其中a,b,p都在长整型范围以内。保证p的两倍不超过长整型。
分析:如果两个大整数相乘,结果取幂,虽然结果在整型范围以内,但是中间结果可能超过长整型。
所以可以把乘法操作用快速加来代替。

void ksc(LL a,LL b,LL p) //求a*b%p
{
	LL res=0; //此处要初始化为0.
	a%=p;
	while(b)
	{
		if(b&1)res=(res+a)%p;
		a=(a+a)%p;
		b>>=1;
	}
	return res;
}

有了快速乘以后,对于长整型的幂取模,我们也可以解决了。使用快速加来代替乘法即可。
例:求 a b % p a^b\%p ab%p的结果, a , b , p a,b,p a,b,p的值不超过 1 0 1 6 10^16 1016.
分析:如果使用乘法,则两个长整型数相乘,结果可能超出长整型。所以可以用快速加来代替乘法。
代码如下:

#include<bits/stdc++.h>
using namespace std;
#define LL long long int
LL a,b,c;
LL ans;
LL quickmul(LL a,LL b,LL p)
{
    LL res=0;
    while(b)
    {
        if(b&1)res=(res+a)%p;
        a=(a+a)%p;
        b>>=1;
    }
    return res;
}

LL quickpow(LL a,LL b,LL p)
{
    LL res=1;
    while(b)
    {
        if(b&1)res=quickmul(res,a,p);
        a=quickmul(a,a,p);
        b>>=1;
    }
    return res;
}
int main()
{
    while(scanf("%lld%llld%lld",&a,&b,&c)!=-1,a||b||c)
    {
        ans=quickpow(a,b,c);
        printf("%lld\n",ans);
    }
    return 0;
}

同余等价类、剩余系、缩系

在模意义下,每一个数表示的是一个同余等价类。比如在模3的意义下,1表示的是所有除以3余数为1的整数。所以 0 0 0表示的是 { 0 , 3 , 6 , 9 , … , } \{0,3,6,9,\dots,\} {0,3,6,9,,} , 1 1 1表示的是 { 1 , 4 , 7 , … , } \{1,4,7,\dots,\} {1,4,7,,},而 2 2 2表示的是 { 2 , 5 , 8 , … , } \{2,5,8,\dots,\} {2,5,8,,}.
可以发现,在模意义下,所有的非负整数可以被分为若干同余等价类。

模p的剩余系指的是 { 0 , 1 , 2 , … , p − 1 } \{0,1,2,\dots,p-1\} {0,1,2,,p1},即小于p的所有非负整数,这个集合中包含了所有模p的余数。集合中的每一个数其实代表一个同余等价类。这个集合称为模p的剩余系,记为 Z p Z_p Zp
如p为6,则 Z p = { 0 , 1 , 2 , 3 , 4 , 5 } Z_p=\{0,1,2,3,4,5\} Zp={0,1,2,3,4,5}.
在模p的剩余系中,与p互质的数的集合,称为模p的缩系,记为 Z p ∗ Z_p^* Zp.
如p为6,则 Z p ∗ = { 1 , 5 } Z_p^*=\{1,5\} Zp={1,5}.
缩系又称为简化剩余系。

质数及其筛法

如果一个自然数a,只能被1和它自身整除,且不能被其他数整除,则a为质数。换句话说,质数只有两个因子。
注意:1不是质数。
100以内的质数有:2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,91,97
例1:判断一个数n是否为质数。
可以枚举 [ 2 , n − 1 ] [2,n-1] [2,n1],如果n在这个范围内有因子,则n不是质数。这个方法的时间复杂度为 O ( n ) O(n) O(n)
更好的方法是枚举 [ 2 , ( n ) ] [2 ,\sqrt(n)] [2,( n)],时间复杂度为 O ( s q r t ( n ) ) 。 O(sqrt(n))。 O(sqrt(n))因为n的因子是成对出现的,如果 i ∣ n i | n in,则 n i ∣ n \frac n i |n inn,而 i , n i i,\frac n i i,in 必有至少一个在 [ 2 , ( n ) ] [2,\sqrt(n)] [2,( n)]内。
参考代码如下:

#include<bits/stdc++.h>
using namespace std;
int n;
int main()
{
	scanf("%d",&n);
	for(int i=2;i<=sqrt(n);i++)
	if(n%i==0)
	{
		printf("n is not a prime\n");
		return 0;
	}
	printf("n is a prime\n");
	return 0;
}

例2:请输出 [ 1 , n ] [1,n] [1,n]内的所有质数。每行一个质数。n<=100000。
可以利用例1中判断质数的方法,将1~n的所有数都判断一下,如果是质数,就输出它。这种方法的时间复杂度为 O ( n n ) O(n\sqrt n) O(nn )
代码如下:

#include<iostream>
#include<cmath>
using namespace std;
int n;
bool isprime(int n)
{
	for(int i=2;i*i<=n;i++)
	{
		if(n%i==0)return 0;
	}
	return 1;
}
int main()
{
	scanf("%d",&n);
	for(int i=2;i<=n;i++) //将i=1排除掉。
		if(isprime(i))printf("%d\n",i);
	return 0;
}

这个方法还是太慢了。毕竟时间复杂度是 O ( N N ) O(N\sqrt N) O(NN )
下面介绍两种更快的质数筛法。

埃氏筛法.

时间复杂度为 O ( N l o g N ) O(NlogN) O(NlogN)
算法是这样的:先把n以内的2的倍数(不包含2)全部删除,再把n以内的3的倍数(不包含3)全部删除,……,这样做下去,最后剩下的数就全部是质数。
这里的删除其实不算真的删除,只是打上一个标记而已。
每个数都会被它的质因子打一次标记,而一个数的质因子个数不超过log,所以,这个时间复杂度为 O ( N l o g N ) O(NlogN) O(NlogN)
代码参考如下:

#include<iostream>
using namespace std;
#define MAXN 1000005
bool flgs[MAXN];//flgs[i]==0表示i为质数 不考虑i<2的情况
int n,cnt,primes[MAXN];
void getprime(int n)
{
	for(int i=2;i<=n;i++)
	{
		if(flgs[i]==1)continue;
		primes[cnt++]=i;
		for(int j=i;j<=n/i;j++)
		flgs[j*i]=1;
	}
}
int main()
{
	scanf("%d",&n);
	getprime(n);
	for(int i=0;i<cnt;i++)
	printf("%d\n",primes[i]);
	return 0;
}

欧式筛法

在上述的埃氏筛法中,一个数可能被它的各个质因子都筛了一遍,而一个数在质因子是不会超过 l o g N logN logN的,所以时间复杂度为 O ( N l o g N ) O(NlogN) O(NlogN)。而欧式筛法保证每个数只被它的最小质因子筛一遍,这样,时间复杂度为 O ( N ) O(N) O(N)
欧式筛法的过程是这样的:
有一个质数集合Q,一开始,质数集合为空,将最小的质数2加入集合。此时 Q = { 2 } Q=\{2\} Q={2}
从2开始枚举依次枚举倍数a,如果倍数a为质数,即将a加入集合Q。
将质数集合中的每个质数的a倍都删掉,因为这些数都是合数。删除指的是打上删除标记,不需要真的删除掉。显然,未打删除标记的数都是质数了。
比如当前质数集合为 Q = { p 1 , p 2 , … , p k } Q=\{p_1,p_2,\dots,p_k\} Q={p1,p2,,pk},当前枚举到的倍数为 a a a,如果a没有删除标记,则a为质数,先将a加入集合Q。接下来枚举质数集合中的所有质数,则将 a ∗ p 1 , a ∗ p 2 , … , a ∗ p k a*p_1,a*p_2,\dots,a*p_k ap1,ap2,,apk全部打上删除标记。
在当前倍数为a,枚举质数的过程中,若发现a是某个质数 p i p_i pi的倍数时,此时后续的质数就无需再枚举了,可以提前退出。为什么呢?设后续的质数为 p i ′ , ( p i ′ > p i ) p_{i'},(p_{i'}>p_i) pi,(pi>pi),那么那些质数的a倍,其实也是质数 p i p_i pi的倍数。即 a ∗ p i ′ = a ′ ∗ p i a*p_{i'}=a'*p_i api=api,因为p_i<p_{i’},所以, a ′ > a a'>a a>a。因为我们要保证每一个数是被它的最小质因子给删掉, a ∗ p i ′ a*p_{i'} api应该被 p i p_i pi删掉,所以就留给倍数a变成 a ′ a' a再去处理了。

例:求给一个整数n,输出区间[1,n]中的所有质数。
n<=1000000
参考代码如下:

#include<bits/stdc++.h>
using namespace std;
#define MAXN 1000005
int prime[MAXN];
bool delflg[MAXN];
int n,cnt;
void sieve(int x)
{
    for(int i=2;i<=x;i++)
    {
        if(delflg[i]==0)prime[cnt++]=i;
        for(int j=0;j<cnt;j++)
        {
            if(prime[j]*i>x)break;
            delflg[prime[j]*i]=1;
            if(i%prime[j]==0)break;
        }
    }
}
int main()
{
    scanf("%d",&n);
    sieve(n);
    for(int i=0;i<cnt;i++)
    {
        printf("%d\n",prime[i]);
    }
    return 0;
}

例1:给出一个整数 n n n,求 n n n^n nn的最低位的值。 n < = 1 0 16 n<=10^{16} n<=1016
分析:本题即是求 n n n^n nn模10的结果。
HDU1061
参考代码略。

例2:给出一个整数n,求有多少个整数k,满足k^k<n.
1 ≤ n ≤ 1 0 18 1\leq n\leq 10^{18} 1n1018
分析:观察到k其实很小。所以可以直接枚举k,求k的快速幂。
但是因为 n n n很大,所以k的快速幂可能会溢出。
注意:溢出不一定为负数。
本题可以打表,可以发现k不大于15.
如果不大表,一定要防止溢出。因为溢出过后,实际值一定是超过了n的。但是如何发现它溢出了呢?
可以再用除法检测一下。
参考代码:

#include<bits/stdc++.h>
using namespace std;
#define LL long long int
LL qpow(LL a,LL b)
{
    LL res=1,tmp;
    while(b)
    {
        if(b&1)
        {
            tmp=res;
            res=res*a;
            if(a==0||res/a!=tmp)return 0;
        }
        tmp=a;
        a=a*a;
        if(a/tmp!=tmp)return 0;
        b>>=1;
    }
    return res;
}
LL n;
int main()
{
    while(cin>>n)
    {
    LL lz=1;
    while(1)
    {
        LL res=qpow(lz,lz);
        if(res>n||res<=0)break;
        lz++;
    }
    cout<<lz-1<<endl;
    }
    return 0;
}

例3:有一个n的排列,如果存在一个位置 1 < = i < = n 1<=i<=n 1<=i<=n,使得前 i i i个数单调递增或递减,第 i + 1 i+1 i+1个数到第 n n n个数也单调递增或递减。则称它为漂亮的。问漂亮的n排列有多少个?你只需要输出答案模 p p p的结果。 1 ≤ n , p ≤ 1 0 18 1\leq n,p\leq10^{18} 1n,p1018
source:hdu5187
分析:可以找规律,得到递推式为 a n s = 2 n − 2 ans=2^n-2 ans=2n2.
这个式子其实也可以推出来。
先考虑从大到小依次选择这n个数来摆放。从第二个数开始,它只能放在已放好的那些数的左边或右边,这样形成的是一个单峰的排列。一共有 2 n − 1 2^{n-1} 2n1种。这里边包含了所有元素单调递增或所有元素单调递减的排列。
单谷排列也类似的,只需要由小到大选择这n个数即可。摆放的方法是一样的。这又有 2 n − 1 2^{n-1} 2n1种。然后其中也包含了单调递增或单调递减这两种方案,这两种在单峰排列中已经算过了。
所以答案 a n s = 2 ∗ 2 n − 1 − 2 = 2 n − 2 ans=2*2^{n-1}-2=2^n-2 ans=22n12=2n2
考虑一下特殊的几种情况:比如p=1或n=1等等。
然后因为 n , p n,p n,p都是长整型,所以快速幂可能爆长整型,要用快速加来代替乘法。
参考代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
#define LL long long int
LL n,p;
LL qmul(LL a,LL b,LL p)
{
    LL res=0;
    while(b)
    {
        if(b&1)res=(res+a)%p;
        a=(a+a)%p;
        b>>=1;
    }
    return res;
}
LL qpow(LL n,LL p)
{
    LL res=1,a=2;
    while(n)
    {
        if(n&1)res=qmul(res,a,p);
        a=qmul(a,a,p);
        n>>=1;
    }
    return res;
}

int main()
{
    while(scanf("%lld%lld",&n,&p)!=-1)
    {
        if(p==1)printf("0\n");
        else if(n==1)printf("%d\n",n);
        else printf("%lld\n",(qpow(n,p)+p-2)%p);
    }
    return 0;
}

例4:给两个整数n和k,令 f ( i ) = i k f(i)=i^k f(i)=ik,求 f ( 1 ) + f ( 2 ) + ⋯ + f ( n ) f(1)+f(2)+\dots+f(n) f(1)+f(2)++f(n)的值。这个值可能很大,你只需要输出结果模 1 0 9 + 7 10^9+7 109+7的值。最多有T组数据。
1 < = n < = 10000 , 0 < = k < = 5 , T < = 20 1<=n<=10000,0<=k<=5,T<=20 1<=n<=10000,0<=k<=5,T<=20
分析:k很小,直接模拟即可。

例5:给出n对整数a和b,和一个模数m,求 ( a 1 b 1 + a 2 b 2 + ⋯ + a k b k ) % m (a_1^{b_1}+a_2^{b_2}+\dots+a_k^{b_k})\%m (a1b1+a2b2++akbk)%m的值。
poj1995

最大公约数与最小公倍数

一般的,设 a 1 , a 2 , a 3 , … , a k a_1,a_2,a_3,\dots,a_k a1,a2,a3,ak k k k个正整数,如果存在一个正整数 d d d,使得 d ∣ a 1 , d ∣ a 2 , … d ∣ a k d| a_1,d\mid a_2,\dots d|a_k da1,da2,dak,那么 d d d则为 a 1 , a 2 , … , a k a_1,a_2,\dots,a_k a1,a2,,ak的公约数。在所有公约数中,最大的称为最大公约数,记为 g c d ( a 1 , a 2 , … , a k ) gcd(a_1,a_2,\dots,a_k) gcd(a1,a2,,ak),显然它是存在的,至少为1。当 g c d = 1 gcd=1 gcd=1时,称这 n n n个数是互质的或既约的。公约数一定是最大公约数的约数。
一般的,设 a 1 , a 2 , a 3 , … … a k a_1,a_2,a_3,……a_k a1,a2,a3,ak k k k个正整数,如果存在一个正整数 d d d,使得 a 1 ∣ d , a 2 ∣ d , a 3 ∣ d , … … a k ∣ d a_1|d,a_2|d,a_3|d,……a_k|d a1d,a2d,a3d,akd,那么 d d d则为 a 1 , a 2 , … … a k a_1,a_2,……a_k a1,a2,ak的公倍数,其中最小的称为最小公倍数数,记为 l c m ( a 1 , a 2 , … … , a k ) lcm(a1,a2,……,ak) lcm(a1,a2,,ak),显然它是存在的。公倍数一定是最小公倍数的倍数。
定理: l c m ( a , b ) × g c d ( a , b ) = a × b lcm(a,b) \times gcd(a,b)=a \times b lcm(a,b)×gcd(a,b)=a×b
证明:将 a , b a,b a,b进行质因子分解,设 a , b a,b a,b的质因子集合并集为 { p 1 , p 2 , … , p n } \{p_1,p_2,\dots,p_n\} {p1,p2,,pn}

a = p 1 k 1 p 2 k 2 … p n k n a=p_1^{k_1}p_2^{k_2}\dots p_n^{k_n} a=p1k1p2k2pnkn 其中 0 ≤ k 1 , 0 ≤ k 2 , 0 ≤ k 3 , … 0 ≤ k n 0\leq k_1,0\leq k_2,0\leq k_3,\dots 0\leq k_n 0k1,0k2,0k3,0kn
b = p 1 j 1 p 2 j 2 … p n j n b=p_1^{j_1}p_2^{j_2}\dots p_n^{j_n} b=p1j1p2j2pnjn 其中 0 ≤ j 1 , 0 ≤ j 2 , 0 ≤ j 3 , … , 0 ≤ j n 0\leq j_1,0\leq j_2, 0\leq j_3,\dots,0\leq j_n 0j1,0j2,0j3,,0jn
那么显然
g c d ( a , b ) = p 1 m i n ( k 1 , j 1 ) p 2 m i n ( k 2 , j 2 ) … p n m i n ( k n , j n ) gcd(a,b)=p_1^{min(k_1,j_1)}p_2^{min(k_2,j_2)}\dots p_n^{min(k_n,j_n)} gcd(a,b)=p1min(k1,j1)p2min(k2,j2)pnmin(kn,jn)
l c m ( a , b ) = p 1 m a x ( k 1 , j 1 ) p 2 m a x ( k 2 , j 2 ) … p n m a x ( k n , j n ) lcm(a,b)=p_1^{max(k_1,j_1)}p_2^{max(k_2,j_2)}\dots p_n^{max(k_n,j_n)} lcm(a,b)=p1max(k1,j1)p2max(k2,j2)pnmax(kn,jn)
∵ m i n ( k i , j i ) + m a x ( k i , j i ) = k i + j i \because min(k_i,j_i)+max(k_i,j_i)=k_i+j_i min(ki,ji)+max(ki,ji)=ki+ji
∴ g c d ( a , b ) ∗ l c m ( a , b ) = p 1 k 1 + j 1 ∗ p 2 k 2 + j 2 … p n k n + j n = a ∗ b \therefore gcd(a,b)*lcm(a,b)=p_1^{k_1+j_1}*p_2^{k_2+j_2}\dots p_n^{k_n+j_n}=a*b gcd(a,b)lcm(a,b)=p1k1+j1p2k2+j2pnkn+jn=ab

辗转相除法
g c d ( a , b ) = g c d ( b , a % b ) gcd(a,b)=gcd(b,a\%b) gcd(a,b)=gcd(b,a%b)
证明:
g c d ( a , b ) = P , 则 a = k P , b = g P , g c d ( b , a gcd(a,b)=P,则a=kP,b=gP,gcd(b,a% gcd(a,b)=P,a=kP,b=gP,gcd(b,a

更相减损术的证明方法和辗转相除法差不多。
中国古代,九章算术中提到了一种求最大公约数的方法,即更相减损术。
如果要对分式 a / b a/b a/b约分,如果a,b都是偶数,可以将a,b都折半;否则,将a和b交替地减去对方,直到最后两者相等,那么这个数可以做为原来a,b的最大公约数。

int gcd(int a,int b)
{
	if(a%b==0)return b;
	return gcd(b,a%b);
}

裴蜀定理

如果 a , b a,b a,b的最大公约数为 d d d,且d能整除c,则存在正整数x和y,满足ax+by=c。
证明:
a ′ = a / d , b ′ = b / d , 则 a ′ x + b ′ y = 1 a'=a/d,b'=b/d,则a'x+b'y=1 a=a/d,b=b/d,ax+by=1,此时, a ′ , b ′ a',b' a,b互质。即我们只需要证明:对于互质的两个整数 a ′ , b ′ a',b' a,b,必存在一个整数 x x x,满足 a ′ x % b ′ = 1 a'x\%b'=1 ax%b=1 即可。 (1)

引理一:如果 a , b a,b a,b为正整数,且 a , b a,b a,b互质,则不存在小于 b b b的正整数k,使得 0 ≡ k ∗ a ( m o d b ) 0 \equiv k*a \pmod b 0ka(modb)
证明显然。用反证法,如果存在 0 < k < b 0<k<b 0<k<b,满足 0 ≡ k ∗ a ( m o d b ) 0 \equiv k*a \pmod b 0ka(modb)
根据整数唯一分解定理, k ∗ a k*a ka中一定包含 b b b的所有质因子,而 a a a b b b互质, a a a中不可能包含 b b b中的质因子,所以必然k是b的倍数。而 0 < k < b 0<k<b 0<k<b,所以, k k k不可能包含 b b b中所有质因子。

推论:如果 a , b a,b a,b为正整数,且 a , b a,b a,b互质, 0 , a , 2 ∗ a , 3 ∗ a , … , ( b − 1 ) ∗ a 0,a,2*a,3*a,\dots,(b-1)*a 0,a,2a,3a,,(b1)a,这些数模b,余数互不相等。
证明:如果存在两个不同的数设为 i ∗ a , j ∗ a i*a,j*a ia,ja,它们模 b b b的余数相等,则 ( i − j ) ∗ a % b (i-j)*a\%b (ij)a%b模b的余数为 0 0 0
而因为 0 < i < n , 0 < j < n 0 \lt i \lt n,0 \lt j \lt n 0<i<n,0<j<n,假设 i > j i>j i>j,则 0 < ( i − j ) < n 0 \lt (i-j)\lt n 0<(ij)<n,这与引理一矛盾。
得证。

引理二:如果 a , b a,b a,b互质,则必存在一个整数 k k k,满足 k ∗ a % b = 1 k*a\%b=1 ka%b=1.
证明:根据推论,这些数模b的结果只能是集合 { 0 , 1 , …   b − 1 } \{0,1,\dots\,b-1\} {0,1,b1}中的数,而这些结果互不相等,且有b个,所以其中必有一个为1。

根据引理2,如果 a , b a,b a,b互质,则必存在一个整数 k k k,满足 k ∗ a % b = 1 k*a\%b=1 ka%b=1,即 k ∗ a − p ∗ b = 1 k*a-p*b=1 kapb=1
于是,裴蜀定理得证。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值