2140B Editorial (1049 round)
Разница между ru1 и en1, 8881 символ(ов) изменены
# Editorial: Concatenation & Divisibility (extended version of CF 2140B)↵
 ↵
*Below is a guide for solving the **extended version of problem 2140B**, where instead of outputting just any valid solution, we describe how to enumerate **all** valid integers $y$.↵
This problem is much deeper than just printing the trivial $y=2x$.*↵
 ↵
---↵
 ↵
## Problem statement (recap)↵
 ↵
We are given an integer $x$ ($1 \le x < 10^8$).↵
We want to find an integer $y$ ($1 \le y < 10^9$) such that↵
 ↵
$$↵
x\#y \equiv 0 \pmod{x+y}, ↵
\quad\text{where}\quad↵
x\#y = x \cdot 10^k + y,↵
$$↵
 ↵
and $k$ is the number of digits of $y$.↵
 ↵
The original problem (CF 2140B) only required outputting **any** valid $y$.↵
Here we discuss the structural description of **all solutions** and two efficient constructive algorithms.↵
 ↵
---↵
 ↵
## Key equivalence↵
 ↵
The condition is:↵
 ↵
$$↵
x \cdot 10^k + y \equiv 0 \pmod{x+y}↵
\ \iff\↵
x(10^k-1) \equiv 0 \pmod{x+y}.↵
$$↵
 ↵
Let $d=\gcd(x,y)$, $x=ad,\ y=bd$. Then $x+y = d(a+b)$.↵
The divisibility condition becomes:↵
 ↵
$$↵
d(a+b) \mid ad(10^k-1) \ \iff\ (a+b)\mid a(10^k-1).↵
$$↵
 ↵
Since $\gcd(a,a+b)=1$, we conclude:↵
 ↵
$$↵
\boxed{\,a+b \mid 10^k-1\,}.↵
$$↵
 ↵
Denote $M=a+b$, which is a divisor of $R_k = 10^k-1$.↵
Then $x+y = dM \implies y = dM - x$.↵
 ↵
Thus, all solutions are described by:↵
 ↵
$$↵
\boxed{\,y = dM - x,\quad d \mid x,\quad M \mid (10^k-1),\quad 10^{k-1}\le y < 10^k\,}.↵
$$↵
 ↵
The last inequality ensures that $y$ has exactly $k$ digits.↵
Equivalently:↵
 ↵
$$↵
\left\lceil \frac{x+10^{k-1}}{d}\right\rceil \le M \le \left\lfloor \frac{x+10^k-1}{d}\right\rfloor.↵
$$↵
 ↵
---↵
 ↵
## Solution 1: Factorization and divisor lists↵
 ↵
**Idea.**↵
For each $k=1..9$, factorize $R_k=10^k-1$ and store all divisors in sorted arrays $D_k$.↵
For a given $x$:↵
 ↵
1. Factorize $x$ using primes up to $\sqrt{x}$.↵
2. Generate all divisors $d \mid x$.↵
3. For each $d$ and $k$, compute the interval for $M$.↵
4. Use binary search on $D_k$ to find any divisor $M$ in this interval.↵
5. Return $y = dM - x$.↵
 ↵
**Correctness.**↵
By construction, $M \mid (10^k-1)$ and $d\mid x$ guarantee the divisibility condition.↵
The interval ensures that $y$ has exactly $k$ digits.↵
Thus, every valid $y$ arises in this way.↵
 ↵
**Complexity.**↵
 ↵
* Precomputation: divisors of $10^k-1$ for $k\le 9$ (constant).↵
* Per test: factorization of $x$ ($O(\pi(\sqrt{x}))$) + divisor generation ($O(\tau(x))$) + binary searches ($O(\tau(x) \cdot 9 \cdot \log |D_k|)$).↵
  With early exit after the first found solution, this is very fast.↵
 ↵
### Code (C++17)↵
 ↵
```cpp↵
#include <bits/stdc++.h> ↵
using namespace std;↵
 ↵
using int64 = long long;↵
 ↵
vector<int> sieve_primes(int limit = 31623) {↵
    vector<bool> is_prime(limit + 1, true);↵
    is_prime[0] = is_prime[1] = false;↵
    for (int i = 2; i * i <= limit; ++i)↵
        if (is_prime[i])↵
            for (int j = i * i; j <= limit; j += i) is_prime[j] = false;↵
    vector<int> primes;↵
    for (int i = 2; i <= limit; ++i) if (is_prime[i]) primes.push_back(i);↵
    return primes;↵
}↵
 ↵
vector<pair<int64,int>> factorize_ll(int64 n, const vector<int>& primes) {↵
    vector<pair<int64,int>> f;↵
    for (int p : primes) {↵
        if (1LL * p * p > n) break;↵
        if (n % p == 0) {↵
            int cnt = 0;↵
            while (n % p == 0) { n /= p; ++cnt; }↵
            f.push_back({p, cnt});↵
        }↵
    }↵
    if (n > 1) f.push_back({n, 1});↵
    return f;↵
}↵
 ↵
void gen_divs(const vector<pair<int64,int>>& f, vector<int64>& divs, int idx=0, int64 cur=1) {↵
    if (idx == (int)f.size()) { divs.push_back(cur); return; }↵
    auto [p, e] = f[idx];↵
    for (int i = 0; i <= e; ++i) {↵
        gen_divs(f, divs, idx + 1, cur);↵
        cur *= p;↵
    }↵
}↵
 ↵
vector<int64> all_divs(int64 n, const vector<int>& primes) {↵
    auto fac = factorize_ll(n, primes);↵
    vector<int64> divs;↵
    gen_divs(fac, divs);↵
    sort(divs.begin(), divs.end());↵
    return divs;↵
}↵
 ↵
int main() {↵
    ios::sync_with_stdio(false);↵
    cin.tie(nullptr);↵
 ↵
    const int KMAX = 9;↵
    const int64 LIM_Y = 1000000000LL;↵
    vector<int64> pow10(KMAX + 1, 1);↵
    for (int k = 1; k <= KMAX; ++k) pow10[k] = pow10[k - 1] * 10;↵
 ↵
    vector<int> primes = sieve_primes();↵
 ↵
    vector<vector<int64>> D(KMAX + 1);↵
    for (int k = 1; k <= KMAX; ++k) {↵
        D[k] = all_divs(pow10[k] - 1, primes);↵
    }↵
 ↵
    int T; cin >> T;↵
    while (T--) {↵
        long long x; cin >> x;↵
        vector<int64> divx = all_divs(x, primes);↵
        bool found = false;↵
 ↵
        for (int k = 1; k <= KMAX && !found; ++k) {↵
            int64 Lk = pow10[k - 1], Uk = pow10[k] - 1;↵
            for (int64 d : divx) {↵
                int64 L = (x + Lk + d - 1) / d;↵
                int64 U = (x + Uk) / d;↵
                if (L > U) continue;↵
                auto itL = lower_bound(D[k].begin(), D[k].end(), L);↵
                auto itU = upper_bound(D[k].begin(), D[k].end(), U);↵
                if (itL == itU) continue;↵
                int64 M = *itL;↵
                int64 y = d * M - x;↵
                if (y >= 1 && y < LIM_Y) {↵
                    cout << y << "\n";↵
                    found = true;↵
                    break;↵
                }↵
            }↵
        }↵
        if (!found) cout << 1 << "\n";↵
    }↵
}↵
```↵
 ↵
---↵
 ↵
## Solution 2: Precompute divisors of $10^k-1$ directly, pure 64-bit check↵
 ↵
**Idea.**↵
Instead of factoring $10^k-1$ with primes, directly compute its divisors by iterating up to $\sqrt{10^k-1}$ for each $k=1..9$.↵
Store sorted lists `dd[k]`.↵
Then repeat the same search procedure:↵
for each $d \mid x$, compute interval for $M$, binary search inside `dd[k]`, and construct $y=dM-x$.↵
 ↵
Divisibility check is done with modular arithmetic fully in 64-bit:↵
 ↵
$$↵
(x \cdot 10^k + y) \bmod (x+y) = ( (x \bmod (x+y)) \cdot (10^k \bmod (x+y)) + y ) \bmod (x+y).↵
$$↵
 ↵
Since $(x+y) < 2 \cdot 10^9$, intermediate multiplications never overflow 64-bit.↵
 ↵
**Complexity.**↵
 ↵
* Precompute divisors of $10^k-1$: $O(\sum_k \sqrt{10^k})$ — constant for $k \le 9$.↵
* Per test: divisor search of $x$ ($O(\sqrt{x})$) + binary search inside `dd[k]` ($O(\tau(x) \cdot 9 \cdot \log |dd[k]|)$).↵
  With early exit, runs comfortably fast.↵
 ↵
### Code (C++17)↵
 ↵
```cpp↵
#include <bits/stdc++.h>↵
using namespace std;↵
 ↵
int pw10[11];↵
vector<int> dd[11];↵
 ↵
inline long long ceil_div(long long a, long long b) {↵
    return (a + b - 1) / b;↵
}↵
 ↵
inline bool divisible_check(long long x, int k, long long y) {↵
    long long den = x + y;↵
    long long t1  = x % den;↵
    long long t2  = pw10[k] % den;↵
    long long lhs = (t1 * t2) % den;↵
    lhs = (lhs + (y % den)) % den;↵
    return lhs == 0;↵
}↵
 ↵
void solve() {↵
    int x; cin >> x;↵
 ↵
    vector<int> del;↵
    for (int i = 1; 1LL * i * i <= x; ++i) {↵
        if (x % i == 0) {↵
            del.push_back(i);↵
            if (x / i != i) del.push_back(x / i);↵
        }↵
    }↵
 ↵
    for (int k = 1; k <= 9; ++k) {↵
        long long Lk = pw10[k - 1], Uk = 1LL * pw10[k] - 1;↵
        const auto &Dv = dd[k];↵
        for (int d : del) {↵
            long long L = ceil_div(1LL * x + Lk, d);↵
            long long U = (1LL * x + Uk) / d;↵
            if (L > U) continue;↵
            auto itL = lower_bound(Dv.begin(), Dv.end(), (int)L);↵
            auto itU = upper_bound(Dv.begin(), Dv.end(), (int)U);↵
            for (auto it = itL; it != itU; ++it) {↵
                long long M = *it;↵
                long long y = 1LL * d * M - x;↵
                if (y >= 1 && y < 1000000000LL && divisible_check(x,k,y)) {↵
                    cout << y << "\n";↵
                    return;↵
                }↵
            }↵
        }↵
    }↵
    cout << 1 << "\n";↵
}↵
 ↵
int main() {↵
    ios::sync_with_stdio(false);↵
    cin.tie(nullptr);↵
 ↵
    pw10[0] = 1;↵
    for (int i = 1; i < 11; ++i) pw10[i] = pw10[i - 1] * 10;↵
 ↵
    for (int k = 1; k <= 9; ++k) {↵
        int num = pw10[k] - 1;↵
        for (int j = 1; 1LL * j * j <= num; ++j) {↵
            if (num % j == 0) {↵
                dd[k].push_back(j);↵
                if (j != num / j) dd[k].push_back(num / j);↵
            }↵
        }↵
        sort(dd[k].begin(), dd[k].end());↵
    }↵
 ↵
    int tt; cin >> tt;↵
    while (tt--) solve();↵
}↵
```↵
 ↵
---↵
 ↵
## Conclusion↵
 ↵
Both solutions rely on the structural criterion:↵
 ↵
$$↵
y = dM - x,\quad d \mid x,\quad M \mid (10^k-1).↵
$$↵
 ↵
They differ only in how divisors of $10^k-1$ are precomputed (via prime factorization or direct sqrt scan) and in the style of the divisibility check.↵
With early exit on the first valid $y$, both run in well under the time limit for $t \le 10^4$.↵
If the extended problem asks for *all* solutions, just loop through all candidate $M$ in the interval instead of breaking at the first.

История

 
 
 
 
Правки
 
 
  Rev. Язык Кто Когда Δ Комментарий
en1 Английский PokemonMaster 2025-09-12 19:01:50 8881 Initial revision for English translation
ru1 Русский PokemonMaster 2025-09-10 14:45:16 8881 Первая редакция (опубликовано)