扩展中国剩余定理

好像OI界都喜欢什么扩展XX,扩展就很不好理解了所以我们干脆给他用一个比较好理解的名字叫合并模线性方程。
先简单介绍下线性同余方程 ax%n=b 其有解需满足(a,n)|b,令d=gcd(a,n) 设t为(a/d)x % (n/d) = (b/d)的唯一解,则ax%n=b的d个解为t,t+n/d,t+2n/d…t+(d-1)n/d。
问题模型:给定模线性同余方程组 r[i]%a[i]=m (1<i<=n,r[i],a[i]均为正整数),判断是否存在最小非负整数解,为一般方程不考虑中国剩余定理的情形。先看前两个方程a1x+r1=m a2y+r2=m, 可以写成ax-by=r2-r1 方程有解需保证(a,b)|(r2-r1),问题等价于寻求ax+by=n的解,我们利用扩展欧几里得先求得ax+by=(a,b)的一组解(x0,y0),于是(x1,y1)=(x0,y0)n/(a,b)为ax+by=n的解。 其他解 x_1,2…≡x1+(b/(a,b))t,y_1,2…≡y1-(a/(a,b))t (0 <=t<=(a,b)-1)。设d=gcd(a,b) x=x+(a2/d)t,则x的最小非负整数解为 x=(x%(a2/d)+(a2/d))%(a2/d); 令f=a2/d;则x=(x%f+f)%f;新的方程变为a1(x+(a2/d)t)+r1=m我们化简得(a1a2/d)t+(a1x+r1)=m r1=a1x+r1; a1=lcm(a1,a2)=(a1a2)/d,故m=r1(mod a1)两个线性同余方程合并成一个等效方程,并继续合并下去,最后r1就是方程组的解了,该方法复杂度为O(nextend_gcd)。
代码如下:

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll; 
ll ai[1000005],bi[1000005],n;
inline ll exgcd(ll a, ll b, ll &x, ll &y)
{
	if(!b)
	{
		x=1;
		y=0;
		return a;
	}
 	ll gcd = exgcd(b, a % b, x, y);
 	 ll t=x;
 	 x=y;
  	 y = t-(a / b) * y;//递归解方程。 
  	 return gcd;
}
inline ll mul(ll a, ll b, ll mod) //必须自己打乘法不然会爆long long 
{
  	ll s = 0;
  	while (b) 
	{
    if (b & 1) s = (s + a) % mod;
    a = (a + a) % mod;
    b >>= 1;
	}
  return s % mod;
}
ll excrt()
{
    ll x,y,k;
    ll M=bi[1],ans=ai[1];//第一个方程的解特判
    for(int i=2;i<=n;i++)
    {
        ll a=M,b=bi[i],c=(ai[i]-ans%b+b)%b;//ax≡c(mod b)
        ll gcd=exgcd(a,b,x,y),bg=b/gcd;
        if(c%gcd!=0) return -1; //判断是否无解,然而这题其实不用
        x=mul(x,c/gcd,bg);
        ans+=x*M;//更新前k个方程组的答案
        M*=bg;//M为前k个m的lcm
        ans=(ans%M+M)%M;
    }
    return (ans%M+M)%M;
}
int main()
{
	ll now,lcm,k;		
	ll x,y;
	cin>>n;
	for(int i=1;i<=n;i++)	
	{
		cin>>bi[i]>>ai[i];
	}
	cout<<excrt();
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值