exgcd 线性同余方程

http://139.224.237.251:23333/problem/3003
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)

#define forn(i,n)  for(int i=0;i<n;i++)
#define rep(i,a,n) for(int i=a;i<=n;i++)
const int maxn=1e5+5;	//200堆 
const int INF=0x3f3f3f3f;
typedef __int128 ll;

int ww[maxn];
void __print(ll x){
	if(x>=10)
		__print(x/10);
	putchar(x%10+'0');
}
void print(ll x){
	if(x<0)
	{
		x=-x;
		putchar('-');
	}
	__print(x);
}
ll gcd(ll a,ll b){
	return b?gcd(b,a%b):a;
}
ll exgcd(ll a,ll b,ll &x,ll &y){
	if(b==0){
		x=1;
		y=0;
		return a;
	}
	ll r=exgcd(b,a%b,x,y);
	ll t=x;	//x1
	x=y;	//x2=y1
	y=t-a/b*y;	//y2=x1-a/b*y1
	return r;
}
/*ll _minx(ll a,ll c,ll cc){
		ll minx=0;
		ll x,y,d=exgcd(a,c,x,y),t=c/d; //exgcd求x0 
		minx=x*cc/d;
		minx=(minx%t+t)%t;
		return minx;
}*/
long long aaa,bbb,ccc;
ll a,b,c;
int main(){

	while(scanf("%lld %lld %lld",&aaa,&bbb,&ccc)!=EOF){
		a=(ll)aaa;
		b=(ll)bbb;
		c=(ll)ccc;
		if(c==1)
		{
			cout<<"God plz"<<endl;
			continue;
		}
		if(b%c==1){
			cout<<0<<endl;
			continue;
		}
		ll cc=(c-b+1)%c;
		if(cc%gcd(a,c)){	//x无解 
			cout<<"God plz"<<endl;
			continue; 
		}
		ll minx=0;
		ll x,y,d=exgcd(a,c,x,y),t=c/d; //exgcd求x0 
		minx=x*cc/d;	//乘c/r
		minx=(minx%t+t)%t;	//必须先mod t
		print(minx);
		cout<<endl;
	}
	return 0;
}

ax’+by’=c
ax0+by0=gcd(a,b)=r;
x’=x0c/r;
y’=y0
c/r
X=x0+t*b/gcd(a,b) 常数
x0=X%t;

ax%n=b
X=x0+t*n/gcd(a,n)

本题
(aX+b)%c=1
aX+b=k*c+1
aX=(k-1)*c+(c-b+1)
aX%c=(c-b+1)%c=cc

X=x0+t*c/gcd(a,c)

t=c/gcd(a,c)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值