# Tutorial for D - Yet Another Real Number Problem
## Problem overview
[Link to problem](https://codeforces.com/contest/2035/problem/D)
**Tags:** ==binary search, bitmasks, data structures, dp, greedy, implementationmath, two pointers.==
I suppose that you've read and understand the problem statement, now we head to the editorial.
## Solution
My idea is to maintain the list of number that can be divided by $2$ and contribute to the current number.
More formally, if we iterate up to position $i$, we will have a **priority_queue** with a **pair<int, int>**, for any number $x = 2^y \times v$, it is stored as $[v, y]$. For example, if the number is $20 = 2^2 \times 5$, then it is stored as $[5, 2]$, if the number is $120 = 2^3 \times 3 \times 5$, then it is stored as $[15, 3]$.
The top value in the **priority_queue** is the smallest ones (as we construct this greedily).
Suppose that we reach a pair of value $[x, cnt]$ in **pq** and currently iterate up to position $i$ . How can we check whether we should perform all operations for this pair to contribute for $a[i]$ ?
We also break $a[i]$ down as mentioned earlier (i.e $a[i] = 2^p \times y$), then we can compare the value before and after performing all operations :
- Before : $y \times 2^p + x \times 2^{cnt}$
- After : $y \times 2^{p + cnt} + x$
The total sum can increase only if the after value is $\geq$ than the berfore value, that is :
$$
\begin{align}
y \times 2^{p + cnt} + x &\geq y \times 2^p + x \times 2^{cnt} \\
\Leftrightarrow\text{ } y \times 2^{p + cnt} - y \times 2^p &\geq x \times 2^{cnt} - x \\
\Leftrightarrow\text{ } y \times 2^p \times 2^{cnt} - y \times 2^p &\geq x \times 2^{cnt} - x \\
\Leftrightarrow\text{ } y \times 2^p \times (2^{cnt} - 1) &\geq x \times (2^{cnt} - 1) \\
\Leftrightarrow\text{ } y \times 2^p &\geq x
\end{align}
$$
We've just broken it down to a very easy comparable expression, now this is how i compare it :
- If $p > 31$, then $y \times 2^p \geq x$ is always true.
- If $p <= 31$, then it fits at least into **long long** data type in **C++**, we just compare it normally.
After knowing that we can perform all operations, we just do it :)
## Implementation
Until now, you can implement it by yourself or read this :
All the variable names i've declared above are compatible with ones in the source code :)
:::spoiler Source code with detailed instructions
```cpp=
#include <bits/stdc++.h>
using namespace std;
/*
John Watson
Handle codeforces : quangminh98
Mua Code nhu mua Florentino !!
*/
#define ll long long
string name = "test";
void solve();
signed main()
{
if (fopen((name + ".inp").c_str(), "r"))
{
freopen((name + ".inp").c_str(), "r", stdin);
freopen((name + ".out").c_str(), "w", stdout);
}
ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int t;
cin >> t;
while (t--) solve();
return 0;
}
// main program
const int mod = 1e9 + 7;
int add(int a, int b) { a += b; if (a >= mod) a -= mod; return a; }
int sub(int a, int b) { a -= b; if (a < 0) a += mod; return a; }
int mul(int a, int b) { return (1ll * a * b) % mod; }
int power(int a, int b)
{
int res = 1;
while (b)
{
if (b % 2 == 1)
res = mul(res, a);
a = mul(a, a);
b /= 2;
}
return res;
}
void solve()
{
int n; cin >> n;
int a[n + 1];
for (int i = 1; i <= n; i++) cin >> a[i];
int cur = 0;
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
for (int i = 1; i <= n; i++)
{
// update current value
cur = add(cur, a[i]);
// get the form of a[i] as described earlier
int p = 0;
while (a[i] % 2 == 0)
{
p++;
a[i] /= 2;
}
int y = a[i];
while (!pq.empty())
{
int x = pq.top().first, cnt = pq.top().second;
// whether we can perform all operations for this
bool great= false;
// compare as analysed earlier
if (p > 31)
great = true;
else
if (1ll * (1 << p) * y >= x) // remember to add 1ll
great = true;
if (!great) break;
pq.pop();
// now we can proceed, we substract the old values while adding new ones
cur = sub(cur, mul(power(2, p), a[i]));
cur = add(cur, mul(power(2, p + cnt), a[i]));
cur = sub(cur, mul(x, power(2, cnt)));
cur = add(cur, x);
// also remember to update the power
p += cnt;
}
// if p is equal to 0, it means the value cannot be divided by 2
// we only push value that can be used
if (p != 0)
pq.push({y, p});
cout << cur << ' ';
}
cout << '\n';
}
```
:::
<br>
**Time complexity :** $O(t \times n \times log_2(n)$
My <span style="color: green;">**Accepted**</span> source code : [Link](https://codeforces.com/contest/2035/submission/288402884)
Having any questions ? DM me in codeforces : [Link](https://codeforces.com/profile/quangminh98)