1. 程式人生 > >Educational Codeforces Round 16 D. Two Arithmetic Progressions

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\n",ans); } int main() { //printf("%d",-1/2); scanf("%lld%lld%lld%lld%lld%lld",&a1,&b1,&a2,&b2,&L,&R); solve(); return 0; }