Problem Link: ODINSONS
Author: tensor_14
Tester: iamreally_john
Difficulty: Medium-Hard
Prerequisites:
Number Theory, Greedy
Problem:
Given two a and b and operations:
-
Subtract 1 from a, making it one unit smaller.
-
Choose any integer p from 2 to k. And, subtract the number (a \mod p) from a.
Find the number of times the given operations to be performed on a to make a==b.
Explanation:
Let L be LCM of all numbers in \begin{bmatrix} 2, &k \end{bmatrix}.
Two cases arise:
Case 1: a % b==0, hence we can’t decrease it using the second operation.
Case 2: a % L!=0. From Case 1, it follows that the optimal transformation will have all numbers divisible by L in \begin{bmatrix} b, & a \end{bmatrix}. We can split the sequence \begin{bmatrix} b, & a \end{bmatrix} into several intervals between the numbers divisible by L(the last interval may have a size less than L). Solve for all the intervals: First interval, last interval, and all intervals in middle. Be vigilant while solving the intervals when there are only 1 or 2 intervals.
At last, multiply the last result by the number of intervals excluding the first and last one. Further, add up obtained 3 values.
Note: You can use BFS to solve problems for one interval. And, further, use DP.
Time Complexity: O\left ( L \right )
Solution:
Setter's Solution
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
using namespace std;
#define ll long long int
#define endl "\n"
ll gcd(ll, ll);
ll timeTaken(ll, ll);
ll a, b, k, dp[16];
void solve(){
ll i, j;
cin>>a>>b>>k;
ll lcm = 1;
for(i = 2; i <= k; i ++)
lcm = lcm * i / gcd(lcm, i);
ll sol = 0,A = a / lcm, B = b / lcm;
sol = (A == B) ? timeTaken(a,b) : timeTaken(a % lcm,0) + (A-B-1) * (timeTaken(lcm-1,0) + 1) + timeTaken(lcm-1,b % lcm) + 1;
cout << sol << endl;
}
int main(){
ios_base::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL);
srand(chrono::high_resolution_clock::now().time_since_epoch().count());
int t = 1;
cin >> t;
while(t--){
solve();
}
return 0;
}
ll gcd(ll a,ll b){
return (b == 0)? a : gcd(b, (a % b));
}
ll timeTaken(ll x, ll b){
ll res = 0;
while (x != b){
ll i, nx = x-1,t;
for(i = 3; i <= k ; i ++)
if ((t = x / i * i)>= b && t < nx)
nx = t;
x = nx; res ++;
}
return res;
}