#include #include #include #include #include #include #include using namespace std; using ll = long long; int64_t mod ( int64_t a , int64_t b ) { return (( a % b ) + b ) % b ; } int64_t MAX = (1LL<<62) - 1 + (1LL<<62); typedef pair pii; typedef pair,vector > pvivi; typedef pair > pivi; //given relative prime a and b, calculate x s.t. a * x = 1 modulo b int64_t mul_inv(int64_t a, int64_t b){ int64_t x0 = 0, x1 = 1; if(b == 1) return 1; while(b) { int64_t q = a / b; int64_t t = b; b = a % b; a = t; t = x0; x0 = x1 - q * x0; x1 = t; } return x1; } int64_t mul_inv_mod(int64_t a, int64_t b, int64_t m){ int64_t x0 = 0, x1 = 1; if(b == 1) return 1; while(b) { int64_t q = a / b; int64_t t = b; b = a % b; a = t; q = q % m; t = x0; x0 = x1 - q * x0; x1 = t; x0 = x0 % m; x1 = x1 % m; } return x1; } int64_t mulmod(int64_t a, int64_t b, int64_t m){ if(abs(a) < abs(MAX / b)) { return a * b % m; } cout << a << " " << b << endl; cout << "dead" << endl; //Detects overflow -> WA solution. return __int128(a) * __int128(b) % m; } int64_t mulmodnodead(int64_t a, int64_t b, int64_t m){ if(abs(a) < abs(MAX / b)) { return a * b % m; } // cout << "dead" << endl; //Detects overflow -> WA solution. return __int128(a) * __int128(b) % m; } //Calculate the X that satisfies all a_i mod x_i and is smallest modulo product_i x_i int64_t my_crt(vector a, vector x, int64_t limit){ int64_t sum = 0, prod = 1; for(int64_t p : x) prod *= p; for(int64_t i = 0; i < a.size(); i++){ int64_t p = prod / x[i]; int64_t m = mul_inv(p, x[i]); sum += mulmod( mulmod(a[i], m, prod), p, prod); } return mod(sum,prod); } pii crt_step(pii a, pii b){ int64_t bigP = a.second * b.second; int64_t result = mod(( mulmod( mulmod(a.first, mul_inv_mod(b.second, a.second, a.second), a.second), b.second, bigP) + mulmod( mulmod(b.first, mul_inv_mod(a.second, b.second, b.second), b.second), a.second, bigP) ), bigP); return { result, bigP }; } pair my_crt2(vector a, vector x, int64_t limit){ pii ans = {a[0],x[0]}; for(int i = 1; i < a.size(); i++){ ans = crt_step(ans,{a[i],x[i]}); if(ans.first >= limit) return {-1,false}; } return {ans.first,true}; } map frogcnt; //count amount of frogs per modulo class map frogmax; //keep the largest position known per modulo class map frogbest; //Keep the largest modulo class per jump distance map > frogties; //Keep all tied modulo classes per jump distance set jump_distances; int64_t donezocnt = 0, crtNext = 0; //Given multiple buckets of elements, return all combinations of buckets. pii combinator(map > &frogties){ //Calculate product of primes and height. int64_t superd = 1, ans_height = 0; for(int64_t p : jump_distances) { superd *= p; ans_height += frogbest[p].second; } int64_t ans = MAX; vector a, x; int64_t maxpos = 0; for(pivi p : frogties){ sort(p.second.begin(),p.second.end()); a.push_back(p.second[0]); x.push_back(p.first); maxpos = max(maxpos, frogmax[{p.first,p.second[0]}]); } int64_t X = my_crt(a,x,ans); int64_t ans_pos = X; for(int64_t j = 0; j < x.size(); j++){ int64_t p = x[j], c = a[j]; int64_t maxpos = frogmax[{p,c}]; int64_t k = ceil((double)(maxpos - X) / (double) superd); ans_pos = max(ans_pos, X + k * superd); } ans = min(ans,ans_pos); return {ans,ans_height}; } int main() { ios::sync_with_stdio(false); cin.tie(0); int64_t n; cin >> n; for(int64_t i = 0; i < n; i++){ //Reading position x and jump distance d int64_t x, d; cin >> x >> d; jump_distances.insert(d); //Category jump distance d, pos x % d has one extra frog frogcnt[{d,x % d}]++; frogmax[{d,x % d}] = max(frogmax[{d,x % d}], x); //If this category is now the biggest, update best category for this jump distance. if(frogcnt[{d,x % d}] == frogbest[d].second) { //We found a tie, add it to the list frogties[d].push_back(x % d); } if(frogcnt[{d,x % d}] > frogbest[d].second) { //Save the best pair: (category offset, size of category) frogties[d] = vector (); frogties[d].push_back(x % d); frogbest[d] = {x % d, frogcnt[{d,x % d}]}; } } pii ans = combinator(frogties); //Find all possible CRT combinations cout << ans.first << " " << ans.second << endl; return 0; }