同余

学习

中国剩余定理

ans=i=1nMiritimodM
其中M=1nmodi,Mi=Mmodi,tiMiM

void solve() 
{
	cin>>n;
	int M=1;
	for(int i=1;i<=n;i++) cin>>mod[i]>>r[i],M=M*mod[i];
	int ans=0;
	int x,y;
	for(int i=1;i<=n;i++) 
	{
		int Mi=M/mod[i];
		ex_gcd(Mi,mod[i],x,y);
		ans=(ans+(Mi*x%M*r[i]%M)+M)%M;
	}
	cout<<ans%M<<endl;
}

扩展中国剩余定理

cin>>n;
	 for(int i=1;i<=n;i++) cin>>mod[i]>>r[i];
	 int x,y;
	 for(int i=1;i<n;i++) 
	 {
	 	int a=mod[i],b=mod[i+1],c=r[i+1]-r[i],g=gcd(a,b);
	 	if(c%g) {cout<<-1<<endl;return;}
	 	a/=g,b/=g,c/=g;
	 	ex_gcd(a,b,x,y);
	 	x=(x*c%b+b)%b;//非负最小整数解
	 	mod[i+1]=mod[i]/gcd(mod[i],mod[i+1])*mod[i+1];//mod[i+1]->lcm(mod[i],mod[i+1])
	 	r[i+1]=(mod[i]*x%mod[i+1]+r[i])%mod[i+1];//新的余数 r[i+1]-r[i]= mod[i]*x+mod[i+1]*y 
	 }
	 //可能在某些题连longlong都会爆,这时候就要用龟速乘
	 cout<<r[n]<<endl;

扩展欧几里得

对于形如ax+by=c,可以用扩欧求出它的一个特解(x0,y0),
判断有解:gcd(a,b)|c
通解:(x0+kb,y0ka)
x最小时,y取最大,反之亦然。
最小非负整数解:xmin=(x%b+b)%b,如果要正整数解,则当xmin=0将它改为b
y同理。
模板

代码

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

void solve() 
{
	cin>>a>>b>>c;
	//求解ax+by=c,问题
	int x,y;
	int d=exgcd(a,b,x,y);
	if(c%d) {cout<<-1<<endl;}//无解
	else 
	{
		a/=d,b/=d,c/=d;//化简公式
		x*=c,y*=c;//因为之前求出的解a*x0+b*y0 = d ,要将解变成c/d倍
		x=(x%b+b)%b;//求x的最小非负整数解
		y=(c-a*c)/b;
	}
}
posted @   Liang2003  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示