数论学习笔记

扩展欧几里得(exgcd)

模板先打上

void exgcd(ll a,ll b)
{
	if(!b)
	{
		x1=1;y1=0;return;
	}
	exgcd(b,a%b);
	ll t=x1;
	x1=y1;y1=t-a/b*y1;
}

扩欧一般用来求解形如 \(ax+by=\gcd(a,b)\) 的不定方程,同时也可以用于求乘法逆元,这之后再讲。

一般来说,通过上述函数求出来的只是一组特解,很多情况下并不是我们需要的答案,所以还要对其进行处理。大多数情况下,题目都会要求我们求 \(x\) 的最小正整数解,此时 \(x\) 一般等于 \((x\%p+p)\%p\) ,这就是 \(x\) 的最小正整数解。

最简单的一道例题:P1082 同余方程

再来看更难的模板题:P5656 【模板】二元一次不定方程(exgcd)

这里要求的是 \(ax+by=c\) 的解,要求很多,我们一个一个来看。首先判无解的情况,这里我设 \(d=\gcd(a,b)\),可以发现,如果 \(d\nmid c\) ,那么这个方程就没有整数解。

为什么呢?可以证明,因为题中 \(x,y\) 均为整数,且 \(a\)\(b\) 一定是 \(d\) 的倍数,所以 \(ax+by\) 也一定是 \(d\) 的倍数,又因为 \(c=ax+by\) ,所以 \(c\%d=0\) 可以得证。

因此,若 \(d\nmid c\) ,则方程无整数解。

若有整数解,我们可以设 \(a'=a/d,b'=b/d,c'=c/d\) , 并用 \(exgcd\) 求出 \(a'x_0+b'y_0=1\) 的一组整数解 \(x_0,y_0\) ,则 \(a'c'x_0+b'c'y_0=c'\) ,两边再同乘 \(d\) ,就得到 \(ac'x_0+bc'x_0=c\) ,由此得到原方程的一组特解 \(x_1=c'x_0,y_1=c'y_0\)

此时我们可以先把 \(x\) 的最小正整数解算出来,即 \(x_{min}=(x\%b+b)\%b\) ,要注意的是若 \(x\%b=0\) ,则 \(x_{min}=b\)

观察方程可知,当 \(x\) 越小时,\(y\) 越大,所以此时与 \(x_{min}\) 对应的那个 \(y\) 即为 \(y\) 的最大正整数解。因为 \(a'x_{min}+b'y_{max}=c'\) ,所以 \(y_{max}=\frac{c'-a'x_{min}}{b'}\)

若此时的 \(y_{max}>0\) ,则说明有正整数解,于是可以同理求出 \(x_{max}\)\(y_{min}\) ,然后因为 \(x_{min}\)\(x_{max}\) 之间每隔 \(b'\) 个数就有一个解,所以正整数解的个数为 \((x_{max}-x_{min})/b'+1\)

若此时 \(y_{max}\le 0\) ,则说明没有正整数解,同理计算出 \(y_{min}\) 即可。

习题

1.P1516 青蛙的约会

2.P2613 【模板】有理数取余

乘法逆元

定义:对于形如 \(ax\equiv 1\pmod b\) 的同余方程,此时 \(x\) 的最小正整数解即为 \(a\) 的逆元。

是不是感觉有些熟悉?没错,这和我们上面的例题P1082一模一样。可以将其化为 \(ax+by=1\) 的不定方程,并使用扩欧求解。

但求逆元不只能用扩欧,还可以用费马小定理+快速幂,但是博主不会,所以等以后再讲。

模板题:P3811 【模板】乘法逆元

除了上述两种方法,还有一种 \(O(n)\) 求逆元的递推方法。这里给出公式,先设 \(inv(i)\)\(i\) 在模 \(p\) 意义下的逆元,则 \(inv(i)=(ll)p-p/i*inv(p\%i)\%p\) ,初始条件为 \(inv(1)=1,inv(0)=0\)

如果要求某一个数模 \(p\) 的逆元,可以使用此公式递归求解,证明请见模板题解。

中国剩余定理(CRT)

中国剩余定理是用于求解形如

\[\begin{cases}x\equiv a_1\pmod {m_1}\\x\equiv a_2\pmod {m_2}\\\ldots\\x\equiv a_k\pmod {m_k}\end{cases} \]

同余方程组的定理,其中 \(m_1,m_2,\ldots,m_k\) 为两两互质的整数,要求找出 \(x\) 的最小非负整数解。

求解过程

首先设 \(M\)\(\prod_{i=1}^km_i\)\(M_i=\frac{M}{m_i}\), \(M_it_i\equiv 1\pmod {m_i}\)

可以看出来 \(t_i\) 即为 \(M_i\) 的逆元,可以构造出一个解 \(x_0=\sum_{i=1}^ka_iM_it_i\) ,我们要求的答案 \(x\) 即为 \(x_0\%M\)

证明请看题解,搞不搞懂无所谓谁叫信息学只看答案呢

模板题:P1495 【模板】中国剩余定理(CRT)/曹冲养猪

主要部分代码

void exgcd(ll a,ll b,int i)
{
	if(!b)
	{
		x[i]=1;y[i]=0;return;
	}
	exgcd(b,a%b,i);
	ll t=x[i];
	x[i]=y[i];y[i]=t-a/b*y[i];
}
int main()
{
	scanf("%lld",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%lld%lld",&a[i],&b[i]);
		M*=a[i];
	}
	for(int i=1;i<=n;i++)
	m[i]=M/a[i];
	for(int i=1;i<=n;i++)
	{
		exgcd(m[i],a[i],i);
		X+=b[i]*m[i]*(x[i]<0?x[i]+a[i]:x[i]);
	}
	printf("%lld",X%M);
	return 0;
}
posted @ 2020-11-25 21:35  洛桃  阅读(124)  评论(0编辑  收藏  举报