【原创】 中国剩余定理 和 拓展中国剩余定理

孙子

Preface

数论学习Part 7。
每天进步一点点,退役不会太丢脸。


联赛只剩十五天,隔靴搔痒智何添?
剩余定理四天一篇,动归图论又几何,数据结构似云烟。
莫再等闲,莫忘时间。

CRT

我们小时候都做过这种问题,一个数 x x x它满足 x ≡ { a 1 m o d    p 1 a 2 m o d    p 2 ⋮ a n m o d    p n x\equiv \begin{cases}a_1 &\mod p_1 \\ a_2 &\mod p_2 \\ &\vdots \\ a_n & \mod p_n\end{cases} xa1a2anmodp1modp2modpn,然后让你求出一个最小的x出来。要求所有的 p p p互质。

遇到这种问题以前的我一般会各写几项出来,然后找相同。
这个时候孙子站了出来,他说出:记 P = ∏ p P=\prod p P=p,则 x = ∑ k = 1 k = n a k P p k t k x=\sum_{k=1}^{k=n}a_k{\frac{P}{p_k}}t_k x=k=1k=nakpkPtk t k 是 P p k 关 于 p k 的 逆 元 t_k是\frac{P}{p_k}关于p_k的逆元 tkpkPpk。这是x的一个解,如果你逆元是最小正逆元,那这个x就是最小正解。

为什么呢?
证明啊……。

先 看 x ≡ a 1 m o d    p 1 。 先看x\equiv a_1 \mod p_1。 xa1modp1
因 为 P p 1 与 p 1 互 质 , 所 以 肯 定 找 得 到 数 t 1 使 得 P p 1 t 1 ≡ 1 m o d    p 1 , 这 个 t 1 被 称 为 P p 1 关 于 p 1 的 逆 元 。 因为\frac{P}{p_1}与p_1互质,所以\href{https://blog.csdn.net/c20182030/article/details/102631472#11_20}{肯定找得到数t_1使得\frac{P}{p_1}t_1\equiv 1\mod p_1},这个t_1被称为\frac{P}{p_1}关于p_1的逆元。 p1Pp1t1使p1Pt11modp1,t1p1Pp1
那 么 就 有 x ≡ a 1 ≡ a 1 × 1 ≡ a 1 P p 1 p 1 m o d    p 1 。 那么就有x\equiv a_1\equiv a_1\times 1\equiv a_1\frac{P}{p_1}p_1\mod p_1。 xa1a1×1a1p1Pp1modp1
因 为 P p 1 = p 2 × p 3 × ⋯ × p n , 所 以 有 a 1 P p 1 p 1 ≡ 0 ( m o d p 2 ) , ( m o d p 3 ) , ⋯   , ( m o d p n ) 。 因为\frac{P}{p_1}=p_2\times p_3\times \cdots \times p_n,所以有a_1\frac{P}{p_1}p_1\equiv 0 \pmod {p_2},\pmod{p_3},\cdots,\pmod {p_n}。 p1P=p2×p3××pna1p1Pp10(modp2),(modp3),,(modpn)←不标准的表达,应当扣分
以 此 类 推 , a 2 P p 2 t 2 就 满 足 模 p 2 时 与 x 同 余 , 模 其 它 p 的 时 候 得 到 0 。 以此类推,a_2\frac{P}{p_2}t_2就满足模p_2时与x同余,模其它p的时候得到0。 a2p2Pt2p2xp0
那 么 这 些 东 西 的 和 — — s = ∑ k = 1 k = n a k P p k t k , 一 定 满 足 s ≡ a 1 + 0 × ( n − 1 ) m o d    p 1 , 那么这些东西的和——s=\sum_{k=1}^{k=n}a_k{\frac{P}{p_k}}t_k,一定满足s\equiv a_1+0\times(n-1)\mod p_1, 西s=k=1k=nakpkPtksa1+0×(n1)modp1 s ≡ a 2 + 0 × ( n − 1 ) m o d    p 2 , s\equiv a_2+0\times(n-1)\mod p_2, sa2+0×(n1)modp2 s ≡ a 3 + 0 × ( n − 1 ) m o d    p 3 , ⋯ , s\equiv a_3+0\times(n-1)\mod p_3,\cdots, sa3+0×(n1)modp3 s ≡ a n + 0 × ( n − 1 ) m o d    p n s\equiv a_n+0\times(n-1)\mod p_n san+0×(n1)modpn,所以可以认为 s s s是原方程的一个解。那么通解就是 s + z P , z ∈ Z s+zP,z\in \Z s+zP,zZ

Q.E.D
就这?

代码

洛谷板子题,双倍经验。

曹冲养猪

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

typedef long long ll;
void Read(ll &p)
{
	p=0;
	int f=1;
	char c=getchar();
	while(c<'0' || c>'9') 
	{
		if(c=='-') f=-1;
		c=getchar();
	}
	while(c>='0' && c<='9')
		p=p*10+c-'0',c=getchar();
	p*=f;
}

void exgcd(ll a,ll b,ll &d,ll &x,ll &y)
{
	if(!b){d=a,x=1,y=0; return;}
	exgcd(b,a%b,d,y,x),y-=(a/b)*x;
}

ll n,ans,d,x,y,P=1,a[1024],p[1024];

int main()
{
	Read(n);
	for(ll i=1;i<=n;i++) Read(p[i]),Read(a[i]),P*=p[i];
	for(ll i=1;i<=n;i++) exgcd(P/p[i],p[i],d,x,y),ans+=a[i]*(P/p[i])%p*x,((ans%=P)+=P)%=P;
	

[TJOI2009]猜数字

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

typedef long long ll;
void Read(ll &p)
{
	p=0;
	int f=1;
	char c=getchar();
	while(c<'0' || c>'9') 
	{
		if(c=='-') f=-1;
		c=getchar();
	}
	while(c>='0' && c<='9')
		p=p*10+c-'0',c=getchar();
	p*=f;
}

void exgcd(ll a,ll b,ll &d,ll &x,ll &y)
{
	if(!b){d=a,x=1,y=0; return;}
	exgcd(b,a%b,d,y,x),y-=(a/b)*x;
}

ll mul(ll a,ll b,ll p)
{
	return ((a*b-(ll)((long double)a/p*b+1e-8)*p)%p+p)%p;
}

ll n,ans,d,x,y,P,a[1024],p[1024];

int main()
{
	Read(n),P=1;
	for(ll i=1;i<=n;i++) Read(a[i]);
	for(ll i=1;i<=n;i++) Read(p[i]),((a[i]%=p[i])+=p[i])%=p[i],P*=p[i];
	for(ll i=1;i<=n;i++) exgcd(P/p[i],p[i],d,x,y),ans+=mul(mul(a[i],P/p[i],P),x,P),((ans%=P)+=P)%=P;
	printf("%lld\n",ans);
}

EXCRT

现在这些p不一定互质了。

我们先看头两个方程吼, { x ≡ a 1 m o d    p 1 x ≡ a 2 m o d    p 2 \begin{cases}x\equiv a_1\mod p_1\\x\equiv a_2 \mod p_2\end{cases} {xa1modp1xa2modp2
那么就有 x = k 1 × p 1 + a 1 = k 2 × p 2 + a 2 ⇒ k 1 × p 1 − k 2 × p 2 = a 2 − a 1 x=k_1\times p_1+a_1=k_2\times p_2+a_2\rArr k_1\times p_1-k_2\times p_2=a_2-a_1 x=k1×p1+a1=k2×p2+a2k1×p1k2×p2=a2a1
g c d ( p 1 , p 2 ) = g gcd(p_1,p_2)=g gcd(p1,p2)=g,则同时除就有 k 1 p 1 g − k 2 p 2 g = a 2 − a 1 g    ⟺    k 1 p 1 g ≡ a 2 − a 1 g m o d    p 2 g k_1\frac{p_1}{g}-k_2\frac{p_2}{g}=\frac{a_2-a_1}{g}\iff k_1\frac{p_1}{g}\equiv \frac{a_2-a_1}{g}\mod {\frac{p_2}{g}} k1gp1k2gp2=ga2a1k1gp1ga2a1modgp2,其中 g c d ( p 1 g , p 2 g ) = 1 gcd(\frac{p_1}{g},\frac{p_2}{g})=1 gcd(gp1,gp2)=1
注意,如果 g ∤ a 2 − a 1 g\nmid {a_2-a_1} ga2a1,则无解。
因为这两个数互质,所以可以求出逆元来,就有: k 1 ≡ a 2 − a 1 g × ( p 1 g ) − 1 m o d    p 2 g k_1\equiv \frac{a_2-a_1}{g}\times (\frac{p_1}{g})^{-1}\mod \frac{p_2}{g} k1ga2a1×(gp1)1modgp2
所以设 k 1 = q × p 2 g + a 2 − a 1 g × ( p 1 g ) − 1 k_1=q\times \frac{p_2}{g}+\frac{a_2-a_1}{g}\times (\frac{p_1}{g})^{-1} k1=q×gp2+ga2a1×(gp1)1

知道 k 1 k_1 k1了,我们就知道了 x x x
x = k 1 × p 1 + a 1 = ( q × p 2 g + a 2 − a 1 g × ( p 1 g ) − 1 ) × p 1 + a 1 = q × p 1 p 2 g + a 2 − a 1 g × ( p 1 g ) − 1 × p 1 + a 1 x=k_1\times p_1+a_1=\left(q\times \frac{p_2}{g}+\frac{a_2-a_1}{g}\times (\frac{p_1}{g})^{-1}\right) \times p_1+a_1=q\times\frac{p_1p_2}{g}+\frac{a_2-a_1}{g}\times (\frac{p_1}{g})^{-1}\times p_1+a_1 x=k1×p1+a1=(q×gp2+ga2a1×(gp1)1)×p1+a1=q×gp1p2+ga2a1×(gp1)1×p1+a1
   ⟺    x ≡ a 2 − a 1 g × ( p 1 g ) − 1 × p 1 + a 1 m o d    p 1 p 2 g \iff x\equiv\frac{a_2-a_1}{g}\times (\frac{p_1}{g})^{-1}\times p_1+a_1 \mod \frac{p_1p_2}{g} xga2a1×(gp1)1×p1+a1modgp1p2

我们把两个同余式合成了一个,太棒了。
看来我们可以做很多次,最后得到一个方程 x ≡ A m o d    B x\equiv A\mod B xAmodB
x x x肯定可以随便解了。

代码

洛谷板子题,【模板】扩展中国剩余定理(EXCRT)

居然一次过编译过样例,还直接A掉了。
我佛了。

太丑了。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

typedef long long ll;
void Read(ll &p)
{
	p=0;
	int f=1;
	char c=getchar();
	while(c<'0' || c>'9') 
	{
		if(c=='-') f=-1;
		c=getchar();
	}
	while(c>='0' && c<='9')
		p=p*10+c-'0',c=getchar();
	p*=f;
}

ll gcd(ll a,ll b){return !b?a:gcd(b,a%b);}
void exgcd(ll a,ll b,ll &d,ll &x,ll &y)
{
	if(!b){d=a,x=1,y=0; return;}
	exgcd(b,a%b,d,y,x),y-=(a/b)*x;
}

ll mul(ll a,ll b,ll p)
{
	return ((a*b-(ll)((long double)a/p*b+1e-8)*p)%p+p)%p;
}

ll n,A,B,C,D,E,d,p,x,y;

int main()
{
	Read(n),n--,Read(B),Read(A);
	while(n--) Read(D),Read(C),d=gcd(B,D),exgcd(B/d,D/d,p,x,y),E=B/d*D,(A+=mul(mul((C-A)/d,x,E),B,E))%=E,B=E;
	printf("%lld\n",(A%B+B)%B);
}

CanKaoWenXian

CRT:其实是在我看了好几篇举个例子就说自己证好了的博客以后,再看到这篇博客的时候突然懂了,所以就以这篇博客为参考文献了。不过这篇文章确实给了我参考。


EXCRT
贞德真的好看。(不是贞德当我没说)

说在后面

问了问数竞的同学,他们的中国剩余定理是证明其有解,然后数学归纳法就整出来了。
好吧,他们确实算不出来逆元。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值