比赛链接
A. 2025
Solution
模拟即可。
C++ Code
#include <bits/stdc++.h>
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::string s;
std::cin >> s;
int sum = 1;
for (auto c: s) {
if (c == '-') {
sum--;
} else {
sum *= 2;
}
if (sum >= 2025) {
std::cout << "YES\n";
return 0;
}
}
std::cout << "NO\n";
return 0;
}
B. 好字符串
Solution
直接统计有多少 i ∈ ( 1 , n ] i \in (1, n] i∈(1,n] 满足 s i − 1 = s i s_{i - 1} = s_i si−1=si,记为 c n t \rm{cnt} cnt,只有 c n t ≤ 1 \rm{cnt \leq 1} cnt≤1 才满足条件。
C++ Code
#include <bits/stdc++.h>
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n;
std::cin >> n;
std::string s;
std::cin >> s;
int cnt = 0;
for (int i = 1; i < n; i++) {
cnt += s[i - 1] == s[i];
}
std::cout << (cnt <= 1 ? "YES\n": "NO\n");
return 0;
}
C. 连续数组
Solution
只要看每个 a i a_i ai 是否升序,且整体无重复元素,并且 max − min + 1 \max - \min + 1 max−min+1 要与集合大小相等。
C++ Code
#include <bits/stdc++.h>
template<class T>
std::istream &operator>>(std::istream &is, std::vector<T> &v) {
for (auto &x: v) {
is >> x;
}
return is;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int q;
std::cin >> q;
std::set<int> set;
for (int i = 0; i < q; i++) {
int k;
std::cin >> k;
std::vector<int> a(k);
std::cin >> a;
if (not std::ranges::is_sorted(a)) {
std::cout << "NO\n";
return 0;
}
for (int x: a) {
if (set.contains(x)) {
std::cout << "NO\n";
return 0;
}
set.insert(x);
}
}
if (*set.rbegin() - *set.begin() + 1 != set.size()) {
std::cout << "NO\n";
} else {
std::cout << "YES\n";
}
return 0;
}
D. mex
题目大意
给定一个长度为 n n n 的非负整数数组 a a a,要求做一下操作若干次,使得 a a a 里面的数都相同。
- 取 m e x = m e x ( a ) \rm{mex = mex(a)} mex=mex(a),然后对 ∀ i ∈ [ 1 , n ] \forall i \in [1, n] ∀i∈[1,n],令 a i : = max ( 0 , a i − m e x ) \rm{a_i := \max(0, a_i - mex)} ai:=max(0,ai−mex)。
求至少要操作几次(可以不操作),如果无法做到,输出 − 1 -1 −1。
其中 m e x ( a ) \rm{mex(a)} mex(a) 表示 a a a 中未出现的最小非负整数,例如 m e x ( { 0 , 1 , 3 } ) = 2 \rm{mex(\{0, 1, 3 \})} = 2 mex({0,1,3})=2。
数据范围
- 1 ≤ n ≤ 1 0 5 , 1\leq n \leq 10^5, 1≤n≤105,
- 0 ≤ a i ≤ 1 0 18 . 0 \leq a_i \leq 10^{18}. 0≤ai≤1018.
Solution
首先对 a a a 排序,若 a 1 ≠ 0 a_1 \neq 0 a1=0,说明 m e x ( a ) \rm{mex(a)} mex(a) 只能是 0 0 0,也就是无法修改 a a a,因此只要看 a a a 的数是否全相等即可。
否则我们记录当前想要出现的 m e x \rm{mex} mex、整个数组被减去的量 s u b \rm{sub} sub 以及操作次数 a n s \rm{ans} ans,初值均为 0 0 0。
若对于当前 x x x,令 x : = x − s u b x := x - sub x:=x−sub,
- 若 x = m e x \rm{x = mex} x=mex,令 m e x : = m e x + 1 \rm{mex := mex + 1} mex:=mex+1;
- 若
x
<
m
e
x
\rm{x < mex}
x<mex,直接
continue
; - 否则这个 m e x \rm{mex} mex 就真的出现了,直接令 x : = x − m e x , s u b : = s u b + m e x , a n s : = a n s + , 1. x := x - mex, \\ sub := sub + mex, \\ ans := ans + ,1. x:=x−mex,sub:=sub+mex,ans:=ans+,1. 如果此时仍有 x > 1 x > 1 x>1,那说明 m e x = 1 \rm{mex} = 1 mex=1,只要减 x − 1 x - 1 x−1 次就能令 x = 1 x = 1 x=1,然后我们再令 m e x = 2 \rm{mex} = 2 mex=2,继续往后遍历。
最后如果剩下的 m e x > 1 \rm{mex} > 1 mex>1,说明一定有没处理完的,答案再 + 1 +1 +1。
时间复杂度 O ( n ) O(n) O(n)
C++ Code
#include <bits/stdc++.h>
using i64 = long long;
template<class T>
std::istream &operator>>(std::istream &is, std::vector<T> &v) {
for (auto &x: v) {
is >> x;
}
return is;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n;
std::cin >> n;
std::vector<i64> a(n);
std::cin >> a;
std::ranges::sort(a);
if (a[0] != 0) {
std::cout << (a[0] != a[n - 1] ? -1: 0) << "\n";
return 0;
}
i64 sub = 0;
i64 mex = 0;
i64 ans = 0;
for (i64 &x: a) {
x -= sub;
if (x == mex) {
mex++;
continue;
}
if (x < mex) {
continue;
}
x -= mex;
sub += mex;
ans++;
if (x > 1) {
sub += x - 1;
ans += x - 1;
}
mex = 2;
}
ans += mex > 1;
std::cout << ans << "\n";
return 0;
}
E. 可划分数组
题目大意
对于一个长度为 n n n 的数组 a a a,将其分成 k k k 份,第 i i i 份的下标区间是 [ l i , r i ] [l_i, r_i] [li,ri],要求:
- l 1 = 1 , l_1 = 1, l1=1,
- r k = n , r_k = n, rk=n,
- ∀ i ∈ [ 1 , k ] , l i < r i , \forall i \in [1, k], \ l_i < r_i, ∀i∈[1,k], li<ri,
- ∀ i ∈ ( 1 , k ] , l i = r i − 1 + 1 , \forall i \in (1, k], \ l_i = r_{i - 1} + 1, ∀i∈(1,k], li=ri−1+1,
- ∀ p ∈ [ l i , r i ] , 至少存在一个 q ∈ [ l i , r i ] ∖ p ,使得 gcd ( a p , a q ) ≠ 1. \forall p \in [l_i, r_i], \ 至少存在一个 \ q \in [l_i, r_i] \setminus {p},使得 \gcd(a_p, a_q) \neq 1. ∀p∈[li,ri], 至少存在一个 q∈[li,ri]∖p,使得gcd(ap,aq)=1.
求 k k k 的可能最大值,如果无法进行分割,输出 − 1 -1 −1。
数据范围
- 1 ≤ n ≤ 2000 , 1 \leq n \leq 2000, 1≤n≤2000,
- 1 ≤ a i ≤ 1 0 9 . 1 \leq a_i \leq 10^9. 1≤ai≤109.
Solution
赛时我用了非常麻烦的分解质因数,然后对位置做标记什么的才过的,下面介绍简单方法。
首先,若 n = 1 n = 1 n=1 或者 ∃ a i = 1 \exists a_i = 1 ∃ai=1,那么一定无法分割。
否则我们考虑 d p \rm{dp} dp,设 d p [ i ] \rm{dp[i]} dp[i] 表示考虑对 [ 1 , i ] [1, i] [1,i] 做分割,能得到的最大 k k k。
显然有转移方程
d p [ i ] = max j ∈ [ 1 , i ) d p [ j − 1 ] + 1 dp[i] = \max\limits_{j \in [1, i)}dp[j - 1] + 1 dp[i]=j∈[1,i)maxdp[j−1]+1
其中 j j j 需要满足区间 [ j , i ] [j, i] [j,i] 是合法的。那么问题变成了如何在 O ( 1 ) O(1) O(1) 或 O ( log n ) O(\log n) O(logn) 的时间判定一段区间 [ l , r ] [l, r] [l,r] 是否合法。
我们令
p
r
e
[
i
]
\rm{pre[i]}
pre[i] 表示
[
1
,
i
)
[1, i)
[1,i) 内最靠右的
j
j
j,使得
gcd
(
a
i
,
a
j
)
≠
1
\gcd(a_i, a_j) \neq 1
gcd(ai,aj)=1,如果没有设为
0
0
0。
接着令
n
x
t
[
i
]
\rm{nxt[i]}
nxt[i] 表示
(
i
,
n
]
(i, n]
(i,n] 内最靠左的
j
j
j,使得
gcd
(
a
i
,
a
j
)
≠
1
\gcd(a_i, a_j) \neq 1
gcd(ai,aj)=1,如果没有设为
n
+
1
n + 1
n+1。
这两个数组可以提前 O ( n 2 log max ( a ) ) O(n^2\log\max(a)) O(n2logmax(a)) 预处理。
对一段区间 [ l , r ] [l, r] [l,r] 来说,如果它是合法的,当且仅当
- ∀ i ∈ [ l , r ] \forall i \in [l, r] ∀i∈[l,r],均有 p r e [ i ] ≥ l ∣ ∣ n x t [ i ] ≤ r pre[i] \geq l \mid \mid nxt[i] \leq r pre[i]≥l∣∣nxt[i]≤r。
那么对于某个 i i i,当 p r e [ i ] ≥ l pre[i] \geq l pre[i]≥l 时,无需看 n x t [ i ] nxt[i] nxt[i],否则就要看所有遍历过的 n x t [ i ] nxt[i] nxt[i] 的最大值是否 ≤ r \leq r ≤r。
简单来说,就是对于固定的 l l l, r r r 从 l l l 开始往右遍历,若 p r e [ r ] < l pre[r] < l pre[r]<l,说明当前 [ l , r ] [l, r] [l,r] 肯定是废了(因为 r r r 就是右端点,不能再往右找 j j j 了),只要令 R = max ( R , n x t [ i ] ) R = \max(R, nxt[i]) R=max(R,nxt[i]),否则若 R ≤ r R \leq r R≤r,就可以更新 d p [ r ] dp[r] dp[r] 的状态。
时间复杂度 O ( n 2 log max ( a ) ) O(\rm{n^2\log\max(a)}) O(n2logmax(a))
- 这个 log \log log 是求 gcd \gcd gcd 时产生的,其实快得很,甚至我感觉就比 O ( 1 ) O(1) O(1) 慢一丢丢。
C++ Code
#include <bits/stdc++.h>
template<class T>
std::istream &operator>>(std::istream &is, std::vector<T> &v) {
for (auto &x: v) {
is >> x;
}
return is;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n;
std::cin >> n;
std::vector<int> a(n);
std::cin >> a;
if (n == 1 or std::ranges::count(a, 1) > 0) {
std::cout << -1 << "\n";
return 0;
}
std::vector pre(n, -1);
for (int i = 0; i < n; i++) {
for (int j = i - 1; j >= 0; j--) {
if (std::gcd(a[i], a[j]) != 1) {
pre[i] = j;
break;
}
}
}
std::vector nxt(n, n);
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (std::gcd(a[i], a[j]) != 1) {
nxt[i] = j;
break;
}
}
}
std::vector<int> dp(n + 1, -1);
dp[0] = 0;
for (int l = 0; l < n; l++) {
for (int r = l, R = 0; r < n and dp[l] != -1; r++) {
if (pre[r] < l) {
R = std::max(R, nxt[r]);
} else if (R <= r) {
dp[r + 1] = std::max(dp[r + 1], dp[l] + 1);
}
}
}
std::cout << dp.back() << "\n";
return 0;
}
F. 最小差值
题目大意
给定整数数组 a , b a, b a,b,长度分别为 n , m n, m n,m,现在请找一个整数 k ∈ [ − 2 ⋅ 1 0 9 , 2 ⋅ 1 0 9 ] k \in [-2 \cdot 10^9, \ 2 \cdot 10^9] k∈[−2⋅109, 2⋅109],使得 ∣ ( ∑ i = 1 n ∣ a i − k ∣ ) − ( ∑ j = 1 m ∣ b j − k ∣ ) ∣ \left|\left(\sum\limits_{i = 1}^{n}|a_i - k|\right) - \left(\sum\limits_{j = 1}^{m}|b_j - k|\right)\right| (i=1∑n∣ai−k∣)−(j=1∑m∣bj−k∣) 最小,输出满足条件的最小 k k k。
数据范围
- 1 ≤ n , m ≤ 1 0 6 , 1 \leq n, m \leq 10^6, 1≤n,m≤106,
- − 1 0 9 ≤ a i , b i ≤ 1 0 9 . -10^9 \leq a_i, b_i \leq 10^9. −109≤ai,bi≤109.
Solution
这种找一个数使得某种求和最小,我们最简单的想法就是直接令 k = a i k = a_i k=ai 或 k = b j k = b_j k=bj。
但是显然我们可以找个很简单的例子 h a c k \rm{hack} hack,比如 a = { − 2 , 1 } , b = { 1 , 2 } a = \{-2, 1\}, \ b = \{1, 2\} a={−2,1}, b={1,2},在 k = 0 k = 0 k=0 时取到最小值。
不过这个思路可以保留做拓展,因为 k ∈ ( − 2 , 1 ) k \in (-2, 1) k∈(−2,1),只要再我们探究一下 k ≠ a i k \neq a_i k=ai 且 k ≠ b j k \neq b_j k=bj 的规律,说不定就能搞定。
若现在 k ∈ a ∪ b k \in a \cup b k∈a∪b,但 k + 1 ∉ a ∪ b k + 1 \notin a \cup b k+1∈/a∪b,我们令 f ( k ) = ( ∑ i = 1 n ∣ a i − k ∣ ) − ( ∑ j = 1 m ∣ b j − k ∣ ) , f(k) = \left(\sum\limits_{i = 1}^{n}|a_i - k|\right) - \left(\sum\limits_{j = 1}^{m}|b_j - k|\right), f(k)=(i=1∑n∣ai−k∣)−(j=1∑m∣bj−k∣), 接着计算 f ( k + 1 ) − f ( k ) f(k + 1) - f(k) f(k+1)−f(k)。
- 对于 a i ≤ k a_i \leq k ai≤k 的 i i i,数量是没变的,设为 c a 1 c_{a_1} ca1,会对表达式产生 c a 1 c_{a_1} ca1 的增量;
- 对于 a i > k a_i > k ai>k 的 i i i,数量同样不变,设为 c a 2 c_{a_2} ca2,会对表达式产生 − c a 2 -c_{a_2} −ca2 的增量;
- 对于 b j ≤ k b_j \leq k bj≤k 的 j j j,数量是没变的,设为 c b 1 c_{b_1} cb1,会对表达式产生 − c b 1 -c_{b_1} −cb1 的增量;
- 对于 b j < k b_j < k bj<k 的 j j j,数量同样不变,设为 c b 2 c_{b_2} cb2,会对表达式产生 c b 2 c_{b_2} cb2 的增量。
这样一来总的增量就是 A = c a 1 + c b 2 − c a 2 − c b 1 A = c_{a_1} + c_{b_2} - c_{a_2} - c_{b_1} A=ca1+cb2−ca2−cb1。
设 k + L ∈ a ∪ b k + L \in a \cup b k+L∈a∪b,于是对于 ∀ x ∈ ( k , k + L ) \forall x \in (k, k + L) ∀x∈(k,k+L),都有 f ( x ) = f ( k ) + A ( x − k ) f(x) = f(k) + A(x - k) f(x)=f(k)+A(x−k) 如果存在一个 x x x 使得 f ( x ) = 0 f(x) = 0 f(x)=0,那 ∣ f ( x ) ∣ = 0 |f(x)| = 0 ∣f(x)∣=0,一定最优。因此要找到这样的 x x x,就先令 f ( x ) = 0 f(x) = 0 f(x)=0,然后化简得到 x k = k − f ( k ) A . x_k = k - \frac{f(k)}{A}. xk=k−Af(k). 由于这个 x k x_k xk 不是整数,所以我们只要找靠近它的两个值 ⌊ x k ⌋ \lfloor x_k \rfloor ⌊xk⌋ 和 ⌈ x k ⌉ \lceil x_k \rceil ⌈xk⌉ 即可。
因此最终我们需要找的点就有:
- ∀ x ∈ a ∪ b , \forall x \in a \cup b, ∀x∈a∪b,
- ∀ ⌊ x k ⌋ , ⌈ x k ⌉ . \forall \lfloor x_k \rfloor, \lceil x_k \rceil. ∀⌊xk⌋,⌈xk⌉.(用上述方式计算得到的)
时间复杂度 O ( ( n + m ) log ( n + m ) ) O(\rm{(n + m)\log (n + m)}) O((n+m)log(n+m))
C++ Code (my implementation)
#include <bits/stdc++.h>
using i64 = long long;
using u64 = unsigned long long;
using u32 = unsigned;
using i80 = __int128_t;
using u80 = unsigned __int128_t;
using f64 = double;
using f80 = long double;
using i16 = short;
using u16 = unsigned short;
constexpr f64 pi = std::numbers::pi;
template<class T>
std::istream &operator>>(std::istream &is, std::vector<T> &v) {
for (auto &x: v) {
is >> x;
}
return is;
}
constexpr int inf = 2E9;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n, m;
std::cin >> n >> m;
std::vector<int> a(n);
std::cin >> a;
std::vector<int> b(m);
std::cin >> b;
std::ranges::sort(a);
std::ranges::sort(b);
std::vector<int> v{-inf, inf};
v.insert(v.end(), a.begin(), a.end());
v.insert(v.end(), b.begin(), b.end());
std::ranges::sort(v);
std::vector<i64> sa(n + 1);
for (int i = 0; i < n; i++) {
sa[i + 1] = sa[i] + a[i];
}
std::vector<i64> sb(m + 1);
for (int i = 0; i < m; i++) {
sb[i + 1] = sb[i] + b[i];
}
auto calc = [&](int k) {
i64 sum = 0;
int i = std::ranges::upper_bound(a, k) - a.begin();
sum += static_cast<i64>(i) * k - sa[i];
sum += (sa[n] - sa[i]) - static_cast<i64>(n - i) * k;
int j = std::ranges::upper_bound(b, k) - b.begin();
sum -= static_cast<i64>(j) * k - sb[j];
sum -= (sb[m] - sb[j]) - static_cast<i64>(m - j) * k;
return sum;
};
std::vector<int> nv;
for (int i = 0; i + 1 < v.size(); i++) {
int l = v[i];
int r = v[i + 1];
if (l + 1 >= r) {
continue;
}
i64 lv = calc(l);
i64 rv = calc(r);
auto sgn = [&](i64 x) {
return x != 0 ? x / std::abs(x): 0;
};
if (sgn(lv) * sgn(rv) > 0) {
continue;
}
int ai = std::ranges::upper_bound(a, l) - a.begin();
int bj = std::ranges::upper_bound(b, l) - b.begin();
int A = ai - (n - ai) - (bj - (m - bj));
if (A == 0) {
continue;
}
f64 kA = l - static_cast<f64>(lv) / A;
for (auto k: {std::floor(kA), std::ceil(kA)}) {
if (l < k and k < r) {
nv.push_back(int(k));
}
}
}
v.insert(v.end(), nv.begin(), nv.end());
std::ranges::sort(v);
v.erase(std::unique(v.begin(), v.end()), v.end());
i64 res = std::numeric_limits<i64>::max() / 4;
int ans = 0;
for (int k: v) {
i64 sum = std::abs(calc(k));
if (res > sum) {
res = sum;
ans = k;
}
}
std::cout << ans << "\n";
return 0;
}
Solution (faster)
上面的做法是我自己的,要两次排序去重,且中间还要不停 upper_bound
,耗时太长,我们不妨延续
f
(
x
)
=
f
(
k
)
+
A
(
x
−
k
)
f(x) = f(k) + A(x - k)
f(x)=f(k)+A(x−k) 的思路,想一个更快的实现。
考虑 k = − 2 ⋅ 1 0 9 k = -2 \cdot 10^9 k=−2⋅109,显然 k ∉ a ∪ b k \notin a \cup b k∈/a∪b,且它的增量 A = 0 + m − n − 0 = m − n A = 0 + m - n - 0 = m - n A=0+m−n−0=m−n。而当不断 k : = k + 1 k := k + 1 k:=k+1 直到第一个 k ∈ a ∪ b k \in a \cup b k∈a∪b 时,
- 若 k = a i k = a_i k=ai,那么增量 A ′ = 1 + m − ( n − 1 ) − 0 = ( m − n ) + 2 A' = 1 + m - (n - 1) - 0 = (m - n) + 2 A′=1+m−(n−1)−0=(m−n)+2;
- 若 k = b j k = b_j k=bj,那么增量 A ′ = 0 + ( m − 1 ) − n − 1 = ( m − n ) − 2 A' = 0 + (m- 1) - n - 1 = (m - n) - 2 A′=0+(m−1)−n−1=(m−n)−2。
经过一通手玩,我们发现,增量 A A A 每碰到一个 a i a_i ai 就 + 2 +2 +2,每碰到一个 b j b_j bj 就 − 2 -2 −2。那我们可以把 a i , b j a_i, b_j ai,bj 都存到同一个数组里(请注意不需要去重),同时记录对应的小增量 + 2 +2 +2 或 − 2 -2 −2。
然后对于式子中的 f ( x ) f(x) f(x),它的含义就是:
- + ( c a 1 ⋅ x − ≤ x 的 a i 的和 ) + (c_{a_1} \cdot x \ - \leq x \ 的 \ a_i \ 的和) +(ca1⋅x −≤x 的 ai 的和);
- − ( > x 的 a i 的和 − c a 2 ⋅ x ) - (> x \ 的 \ a_i \ 的和 - c_{a_2} \cdot x) −(>x 的 ai 的和−ca2⋅x);
- − ( c b 1 ⋅ x − ≤ x 的 b j 的和 ) - (c_{b_1} \cdot x \ - \leq x \ 的 \ b_j \ 的和) −(cb1⋅x −≤x 的 bj 的和);
- + ( > x 的 b j 的和 − c b 2 ⋅ x ) + (> x \ 的 \ b_j \ 的和 - c_{b_2} \cdot x) +(>x 的 bj 的和−cb2⋅x)。
由于我们把 x x x 前面的系数拎出来作为增量 A A A,所以我们只考虑后面那些 a i a_i ai 和 b j b_j bj 的和,处理方式和 A A A 一样。
这样 f ( x ) f(x) f(x) 就是若干个一次函数的并,每一段都是 k x + b kx + b kx+b(注意这里 k k k 是斜率了,也就是上面的增量 A A A; b b b 也不是数组 b b b,而是只考虑了后面那些 a i a_i ai 和 b j b_j bj 的和),而我们要求的就是 min ( ∣ k x + b ∣ ) \min(|kx + b|) min(∣kx+b∣),所以考虑最近的三个点 { − b k − 1 , − b k , − b k + 1 } \{ -\frac{b}{k} - 1, \ -\frac{b}{k}, \ -\frac{b}{k} + 1 \} {−kb−1, −kb, −kb+1} 即可。
C++ Code (faster implementation)
#include <bits/stdc++.h>
using i64 = long long;
constexpr int inf = 2E9;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n, m;
std::cin >> n >> m;
int k = m - n;
std::vector<std::pair<int, int>> v;
v.reserve(n + m + 1);
i64 b = 0;
for (int i = 0; i < n; i++) {
int x;
std::cin >> x;
v.emplace_back(x, 2);
b += x;
}
for (int i = 0; i < m; i++) {
int x;
std::cin >> x;
v.emplace_back(x, -2);
b -= x;
}
v.emplace_back(inf, 0);
std::ranges::sort(v);
int ans = -inf;
i64 res = std::abs(static_cast<i64>(k) * ans + b);
int l = -inf;
for (const auto &[r, add]: v) {
if (k != 0) {
i64 c1 = -b / k;
for (int i = -1; i <= 1; i++) {
i64 c2 = c1 + i;
c2 = std::max<i64>(c2, l);
c2 = std::min<i64>(c2, r);
i64 sum = std::abs(k * c2 + b);
if (res > sum) {
res = sum;
ans = c2;
}
}
}
k += add;
b -= static_cast<i64>(add) * r;
l = r;
}
std::cout << ans << "\n";
return 0;
}