浅谈中国剩余定理
中国剩余定理
定义#
中国剩余定理(CRT)可以求解如下形式的一元线性同余方程组(其中
过程#
-
计算所有模数的积
-
对于第
个方程:-
计算
; -
计算
在模 意义下的逆元 -
计算
(不要对 取模)
-
-
方程组在模
意义下的唯一解为
证明#
我们需要证明上面算法计算所得的
当
其中
即对于任意
因为我们没有对输入的
另外,若
故系数列表
P1495【模板】中国剩余定理(CRT)/ 曹冲养猪 - 洛谷
参考代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,r[11],m[11],mi[11],M=1,ans;
inline void exgcd(int a,int b,int &x,int &y)//扩欧求逆元
{
if(b==0){x=1,y=0;return;}
exgcd(b,a%b,x,y);
int z=x;x=y;y=z-y*(a/b);
}
signed main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>m[i];
M*=m[i];
cin>>r[i];
}
for(int i=1;i<=n;i++)
{
mi[i]=M/m[i];
int x=0,y=0;
exgcd(mi[i],m[i],x,y);//计算mi[i]在模m[i]意义下的逆元x
if(x<0)x+=m[i];//有可能是负数,加上模数即可
ans+=r[i]*mi[i]*x;//累加答案
}
cout<<(ans%M)<<endl;
return 0;
}
Garner 算法#
CRT的另一个用途是用一组比较小的质数来表示一个大的整数。
例如,若
我们可以用以下形式的式子(称作
Garner 算法将用来计算系数
令
把
代入第二个方程得到:
方程两边减
类似地,我们可以得到:
扩展CRT#
上面的朴素 CRT 是求解
一类的同余方程组,但是如果
据某位学长说扩展中国剩余定理跟中国剩余定理没半毛钱关系,一个是用扩展欧几里得,一个是用构造
首先我们从简单入手,考虑只有两个式子的情况
将两个式子变形:
联立:
移项:
在这里需要注意就是这个方程有解的条件是
对于上面的方程,两边同除
转换一下:
此时我们把
同余式两边同除
我们把开头的式子拿过来,把
此时,整个式子中的元素我们都知道了
这个式子可以看作是
其中:
如果是多个式子可以逐个合并。
上面的式子如果你觉得又臭又长可以把
#include<bits/stdc++.h>
#define int __int128
#define N 100010
using namespace std;
int n,x,y,d;
inline int read(){int x=0,f=1;char ch=getchar();while(!isdigit(ch)){f=ch!='-';ch=getchar();}while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return f?x:-x;}
inline void print(int x){if(x>=10)print(x/10);putchar(x%10+48);}
inline void exgcd(int a,int b,int &x,int &y)//扩欧求逆元
{
if(b==0)return d=a,x=1,y=0,void();//d是当前的ab的最大公约数
exgcd(b,a%b,x,y);
int z=x;x=y;y=z-y*(a/b);
}
inline int lcm(int a,int b){return a*b/__gcd(a,b);}//最小公倍数函数
int a,b,A,B;
inline void merge()//合并两个同余方程组
{
exgcd(a,A,x,y);//先求两个值的一组特解和最大公约数
int c=B-b;//计算两个式子的余数的差值
if(c%d)puts("-1"),exit(0);//如果是gcd的倍数说明分母后面是0无解
x=x*c/d%(A/d);//计算右半部分式子的值
if(x<0)x+=A/d;//如果小于0就加上模数
int mod=lcm(a,A);//计算新模数,A,a的最小公倍数
b=(a*x+b)%mod;//计算余数也就是新b的值,
if(b<0)b+=mod;//如果b小于0就直接加上模数
a=mod;//新的模数
}
signed main()
{
n=read();a=read();b=read();
for(int i=2;i<=n;i++)
{
int _A=read(),_B=read();//当前式子的模数,余数
A=_A,B=_B;
merge();//合并
}
print(b%a);
return 0;
}
部分参考自 OI Wiki
作者: 北烛青澜
出处:https://www.cnblogs.com/Multitree/p/17435391.html
本站使用「CC BY 4.0」创作共享协议,转载请在文章明显位置注明作者及出处。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!