您的位置:首页 > 其它

线性同余方程及例题 codeforces 710D

2016-08-23 20:20 387 查看

简述

⎧⎩⎨⎪⎪⎪⎪⎪⎪⎪⎪x≡r1(modm1)x≡r2(modm2)x≡r3(modm3)……

其中m1,m2……不保证互质。

求最小非负整数解x.

中国剩余定理

两个方程

先考虑只有两个方程怎么做。

x≡r1(modm1),x≡r2(modm2)

x=r1+m1∗a=r2+m2∗b

m1∗a−m2∗b=r2−r1

用扩展欧几里得求一组解a,b,那么ans=r1+m1∗a得到了一个解。

会发现ans+k∗lcm(m1,m2)也满足上式。

多个方程

满足x≡r1(modm1),x≡r2(modm2)

相当于x≡ans(modlcm(m1,m2))

把方程放进同余方程组就相当于合并了两个方程。

例题

原题链接

CF 710D

题目大意

给你a1,a2,b1,b2,l,r,

问有多少个l≤x≤r,x=a1∗k′+b1=a2∗l′+b2,满足k′,l′是非负整数。

解题思路

x=k′∗a1+b1⇔x≡a1(modb1)

x=k′∗a2+b2⇔x≡a2(modb2)

这样就转化到两个同余方程。

要求k′,l′≥0⇔x≥max(b1,b2).

问题就解决了。

参考代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define ll long long
#define db double
using namespace std;

ll m1,m2,r1,r2,l,r;

ll ans1,ans2;

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

void Ex_crt(){
ans1=m1;
ans2=r1;
ll x,y,gcd;
gcd=exgcd(ans1,m2,x,y);
if ((r2-ans2) % gcd) {
ans1=-1;
return;
}
ll lcm=ans1/ gcd*m2;
x=x*(r2-ans2)/ gcd;
y=y*(r2-ans2)/ gcd;
ll add=m2 / gcd;
x=(x % add+add) % add;
ans2=lcm;
ans1=r1+x*m1;
ans1=(ans1 % ans2+ans2) % ans2;
}

int main(){
cin>>m1>>r1>>m2>>r2>>l>>r;
//x=r1 (%m1)
//x=r2 (%m2)
Ex_crt();
l=max(l,max(r1,r2));
if (ans1==-1 || l>r) {
puts("0");
return 0;
}
ll ans;
ans=floor((db)(r-ans1)/ans2)-floor((db)(l-ans1)/ans2);
if ((l-ans1) % ans2==0) ans++;
printf("%I64d",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  codeforces