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

简述

xr1(modm1)xr2(modm2)xr3(modm3)

其中 m1,m2 不保证互质。
求最小非负整数解 x .

中国剩余定理

两个方程

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

xr1(modm1),xr2(modm2)

x=r1+m1a=r2+m2b

m1am2b=r2r1

用扩展欧几里得求一组解 a,b ,那么 ans=r1+m1a 得到了一个解。
会发现 ans+klcm(m1,m2) 也满足上式。

多个方程

满足 xr1(modm1),xr2(modm2)
相当于 xans(modlcm(m1,m2))
把方程放进同余方程组就相当于合并了两个方程。

例题

原题链接

CF 710D

题目大意

给你 a1,a2,b1,b2,l,r ,
问有多少个 lxr,x=a1k+b1=a2l+b2 ,满足 k,l 是非负整数。

解题思路

x=ka1+b1xa1(modb1)

x=ka2+b2xa2(modb2)

这样就转化到两个同余方程。
要求 k,l0xmax(b1,b2) .
问题就解决了。

参考代码

#include
#include
#include
#include
#include
#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;
}

你可能感兴趣的:(math,codeforces)