[基础数论]不定方程笔记

2026-07-19 18:58:25

[基础数论]不定方程笔记

Glassy_Sky

·

2023-05-11 21:06:01

·

个人记录

前言

在学习本节内容前,最好先学习同余的基本性质以加深理解。

一堆定理

定理1:

a,b,m,n \in \mathbb Z,c \mid a,c \mid b

c \mid (ma+nb)

证明:

令 a=ce,b=cf ,

代入 ma+nb 再提公因式即可。

定理2:

a,b,c \in \mathbb Z

(a+cb,b)=(a,b)

证明:

由定理1证明二者公因子相同即可。

定理3:

两个不全为零的整数 a,b 的最大公因子是 a,b 线性组合的最小正整数.

证明:令 d 是 a,b 的线性组合中最小的正整数, d = ma + nb , 其中 m,n 是整数,我们将证明 d \mid a,d \mid b 。

由带余除法,得到 a=dq+r, 0≤r

由 a=dq+r 和 d=ma+nb ,得到 r=a-dq=a-q(ma+nb)=(1-qm)a-qnb .

这就证明了整数 r 是 a,b 的线性组合。因为 0 ≤ r < d ,而 d 是 a,b 的线性组合中最小的正整数,

于是我们得到 r=0 (如果 r 不是等于 0 ,那意味着 r 才是所有线性组合中最小的正整数,这与 d 是所有线性组合中最小的正整数矛盾),因此 d \mid a ,同理可得, d \mid b .

我们证明了 a,b 的线性组合中最小的正整数 d 是 a,b 的公因子,剩下要证的是它是 a,b 的最大公因子,为此只需证明 a,b 所有的公因子都能整除 d 。

由于 d = ma + nb ,因此如果 c \mid a 且 c \mid b ,那么由定理2有 c \mid d ,因此 d > c 。

得证。

定理4:

若 a,b 是正整数,

则所有 a,b 的线性组合构成的集合与所有 (a,b) 的倍数构成的集合相同。

证明:由定理1得 a,b 的线性组合都是 (a,b) 倍数。

由定理3得 (a,b) 属于线性组合,其倍数显然也属于线性组合。

得证。

定理5:

a,b,c \in \mathbb Z , m \in \mathbb Z^+ ,d=(c,m)

且有

ac \equiv bc \pmod m

a \equiv b \pmod {m/d}

证明:令 ac=km+bc \to (a-b)c=km

两边同除 d 得到:(a-b)(c/d)=k(m/d)

因为 (c/d) 与 (m/d) 互质,

所以有 (m/d) \mid (a-b)

得到结论:a \equiv b \pmod {m/d}

得证。

推论:

a,b,c \in \mathbb Z , m \in \mathbb Z^+, (c,m)=1

且有

ac \equiv bc \pmod m

则有

a \equiv b \pmod m

定理6:

若 r_1,r_2,…,r_m 是一个模 m 的完全剩余系,且有正整数 a 满足 (a,m)=1

则对任何整数 b 有: ar_1+b,ar_2+b,…,ar_m+b 也是一个模 m 的完全剩余系。

证明:若有 ar_i+b 与 ar_j+b 同余,则有 ar_i 与 ar_j 同余。

由定理5推论可得:此时有 r_i 与 r_j 同余,矛盾!

故定理成立。

朴素欧几里得定理

a,b \in \mathbb Z

(a,b)=gcd(b,a \% b)

证明:

令 a=bq+r ,

得 r=a-bq.

由定理2得,

gcd(a,b)=gcd(a-bq,b)=gcd(r,b)=gcd(a\%b,b)=gcd(b,a\%b)

扩展欧几里得算法

扩展欧几里得算法就是在朴素欧几里得上求一组未知数 (x,y) 的解。

公式推导

对于

ax+by=(a,b)

不妨设 a>b ,

$(2) a>b>0

设 ax_1+by_1=gcd(a,b),bx_2+(a \mod b) y_2

由朴素欧几里得得:gcd(a,b)=gcd(b,a \mod b)

所以 ax_1 + by_1 = bx_2 + (a \mod b)y_2

即 ax_1 + by_1 = bx_2 + (a - \lfloor \frac{a}{b} \rfloor *b)y_2

化简得:ax_1 + by_1 = bx_2 + ay_2 - \lfloor \frac{a}{b} \rfloor *b *y_2

由贝祖等式得 x_1 = y_2 , y_1 = x_2 - \lfloor \frac{a}{b} \rfloor *y_2

裴蜀定理

a,b \in \mathbb Z

则存在

x,y \in \mathbb Z,ax+by=(a,b)

证明:由定理3易证。

推论:

整数 a 与 b 互质,

当且仅当存在整数 m,n 使得 ma+nb=1.

证明:若 ma+nb=1 ,由定理3得 (a,b)=1 ,易证。

二元一次不定方程

对于一些方程形如

ax+by=c

如果 x = x_0, y = y_0 是方程的一个特解,

那么所有的解可以表示为:

code:

```cpp

//二元一次不定方程

#include

#define int long long

using namespace std;

int G,a,b,c,d,x,y;

void exgcd(int a,int b,int& d,int& x,int& y) {

if(!b) {

d=a,x=1,y=0;

return ;

}

exgcd(b,a%b,d,x,y);

int t=x;

x=y,y=t-a/b*y;

return ;

}

signed main() {

scanf("%lld",&G);

while(G--) {

scanf("%lld%lld%lld",&a,&b,&c);

exgcd(a,b,d,x,y);

if(c%d!=0) {

printf("-1\n");

continue;

}

x*=c/d,y*=c/d;

int mx=b/d,my=a/d,minx=-1,maxx=-1,miny=-1,maxy=-1,t;

if(x>0) {

minx=x-(x/mx)*mx;

int ty=y+(x/mx)*my;

if(!minx) minx+=mx,ty-=my;

if(ty>0) maxx=minx+ty/my*mx-mx*(ty%my==0?1:0),t=ty/my+1-(ty%my==0?1:0);

}

else {

minx=x+(-x)/mx*mx+mx;

int ty=y-((-x)/mx+1)*my;

if(ty>0) maxx=minx+ty/my*mx-mx*(ty%my==0?1:0),t=ty/my+1-(ty%my==0?1:0);

}

if(y>0) {

miny=y-(y/my)*my;

int tx=x+(y/my)*mx;

if(!miny) miny+=my,tx-=mx;

if(tx>0) maxy=miny+tx/mx*my-my*(tx%mx==0?1:0);

}

else {

miny=y+(-y)/my*my+my;

int tx=x-((-y)/my+1)*mx;

if(tx>0) maxy=miny+tx/mx*my-my*(tx%mx==0?1:0);

}

if(maxx!=-1) printf("%lld %lld %lld %lld %lld\n",t,minx,miny,maxx,maxy);

else printf("%lld %lld\n",minx,miny);

}

return 0;

}

```

# 多元一次不定方程

对于方程形如

$$a_1x_1 + a_2x_2 + … + a_nx_n = c$$

由前文所述,我们知道

$$a_1x_1 + a_2x_2 = k(a_1,a_2) \ (k \in \mathbb Z)$$

所以原式就可以换成:

$$(a_1,a_2)x + a_3x_3 + … + a_nx_n = c$$

重复以上操作,就可以得到:

$$(a_1,a_2,…,a_{n-1})x + a_nx_n =c$$

再一层层解回去即可。

code:(仅供参考)

```cpp

//多元一次不定方程

#include

#define int long long

using namespace std;

const int maxn=5+5;

long long n,c,a[maxn],ans[maxn];

void exgcd(int a,int b,int& d,int& x,int& y) {

if(!b) {

d=a,x=1,y=0;

return ;

}

exgcd(b,a%b,d,x,y);

int temp=x;

x=y,y=temp-a/b*y;

return ;

}

void f(long long t,int now,int& nc) {

if(now

int x,y,d;

exgcd(t,a[now],d,x,y);

if(nc%d!=0) {

printf("-1");

exit(0);

}

x*=nc/d,y*=nc/d;

ans[now]=y;

if(now==2) ans[now-1]=x;

nc=t*x;

return ;

}

signed main() {

scanf("%lld%lld",&n,&c);

for(int i=1;i<=n;i++)

scanf("%lld",&a[i]);

f(a[1],2,c);

for(int i=1;i<=n;i++)

printf("%lld ",ans[i]);

return 0;

}

```

谁知道黄水晶属性是什么
大掌门超级阵容组建攻略 最强搭配解析