Educational Codeforces Round 16 D. Two Arithmetic Progressions

解线性同余方程组,且方程仅2个,另外得到的x限制在L,R区间内,

观察一下A1K-A2L=B2-B1,便可知,通解(K,L)中会同时增大或同时减小,大可以先使得K,L大于等于0,于是之后只需要考虑让K不断增大且这样得到的x在[L,R]内即可。

由x在[L,R]中,便可以求出K的范围,然后分情况讨论一下就好了。

#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <cstring>
#include <set>
#include <map>
#include <list>
#include <queue>
#include <string>
#include <iostream>
#include <algorithm>
#include <functional>
#include <stack>
#include <bitset>
using namespace std;
typedef long long ll;
#define INF (0x3f3f3f3f)
#define maxn (1000005)
#define mod 1000000007
#define ull unsigned long long
ll a1,b1,a2,b2,L,R;
ll exgcd(ll a,ll b,ll& x,ll& y){
    if(b == 0){
        x = 1,y = 0;
        return a;
    }
    ll g = exgcd(b,a % b,x,y),t = x;
    x = y;
    y = t - a/b*y;
    return g;
}
void solve(){
    ll A = a1,B = a2,C = b2 - b1,x,y;
    ll g = exgcd(A,B,x,y);
    if(C % g != 0){
        puts("0");
        return;
    }
    x = C/g*x;
    ll t = B/g;
    if(x < 0) x = x + (abs(x)/t + 1) * t;
    x = x - (x/t)*t;
    //x为最小非负数
    y = (a1*x+b1-b2)/a2;
    if(y < 0){//令x,y均大于等于0
        y = y + (A/g)*(abs(y)/(A/g) + 1);
        y = y - (y/(A/g))*(A/g);
        x = (a2*y+b2-b1)/a1;
    }
    ll l = (L - b1)/a1,r = (R-b1)/a1,ans;//l <= x <= r
    if(L-b1>=0&&(L-b1)%a1!=0)++l;
    if(R-b1<0&&(R-b1)%a1!=0)--r;
    if(x < l){
        ans = ans + (r-x)/t-(l-x)/t + 1;
        if((l-x)%t != 0) ans--;
    }
    else if(x <= r) ans = (r - x)/t + 1;
    else ans = 0;
    printf("%lld
",ans);
}
int main()
{
    //printf("%d",-1/2);
    scanf("%lld%lld%lld%lld%lld%lld",&a1,&b1,&a2,&b2,&L,&R);
    solve();
    return 0;
}
原文地址:https://www.cnblogs.com/zhuiyicc/p/9882167.html