結果

問題 No.3028 No.9999
ユーザー Tatsu_mr
提出日時 2025-02-21 21:52:39
言語 C++23
(gcc 13.3.0 + boost 1.87.0)
結果
TLE  
実行時間 -
コード長 14,319 bytes
コンパイル時間 6,659 ms
コンパイル使用メモリ 335,224 KB
実行使用メモリ 13,632 KB
最終ジャッジ日時 2025-02-21 21:52:53
合計ジャッジ時間 12,257 ms
ジャッジサーバーID
(参考情報)
judge4 / judge3
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 3
other AC * 5 TLE * 1 -- * 17
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <bits/stdc++.h>
#include <atcoder/convolution>
using namespace std;

#define For(i, a, b) for(int i = (a); i < (b); i++)
#define rep(i, n) For(i, 0, n)
#define rFor(i, a, b) for(int i = (a); i >= (b); i--)
#define ALL(v) (v).begin(), (v).end()
#define rALL(v) (v).rbegin(), (v).rend()

using lint = long long;
using ld = long double;

int INF = 2000000000;
lint LINF = 1000000000000000000;

struct SetupIo {
    SetupIo() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        cout << fixed << setprecision(15);
    }
} setupio;

namespace rklib {

template <class T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &v) {
    os << "[";
    for (auto d : v) os << d << ", ";
    return os << "]";
}

// a <- max(a, b)
template <class T>
bool chmax(T &a, const T &b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}

// a <- min(a, b)
template <class T>
bool chmin(T &a, const T &b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}

// if a < 0: a <- b
// else: a <- min(a, b)
template <class T>
bool chmin_non_negative(T &a, const T &b) {
    if (a < 0 || a > b) {
        a = b;
        return true;
    }
    return false;
}

// floor(num / den)
template <class T>
T div_floor(T num, T den) {
    if (den < 0) num = -num, den = -den;
    return num >= 0 ? num / den : (num + 1) / den - 1;
}

// ceil(num / den)
template <class T>
T div_ceil(T num, T den) {
    if (den < 0) num = -num, den = -den;
    return num <= 0 ? num / den : (num - 1) / den + 1;
}

}  // namespace rklib

namespace rklib {

struct BigInt {
   public:
    BigInt() : BigInt(0) {}
    template <typename T, std::enable_if_t<std::is_integral<T>::value,
                                           std::nullptr_t> = nullptr>
    BigInt(T x) : BigInt(std::vector<T>(1, x)) {}
    template <typename T, std::enable_if_t<std::is_integral<T>::value,
                                           std::nullptr_t> = nullptr>
    BigInt(std::vector<T> a) {
        while (a.size() >= 2 && a.back() == 0) a.pop_back();
        if (a.size() == 1 && a[0] == 0) {
            sgn = 0;
            v = {0};
            return;
        }
        sgn = (a.back() > 0 ? 1 : -1);
        if (sgn < 0) {
            std::transform(a.begin(), a.end(), a.begin(),
                           [](T x) { return -x; });
        }
        v = normalize(a);
    }
    BigInt(std::string s) : sgn(1) {
        if (s[0] == '-') {
            s.erase(s.begin());
            sgn = -1;
        }
        if (s == "0") {
            sgn = 0;
            v = {0};
            return;
        }
        for (int r = int(s.size()), l = std::max(0, r - log10_base); r > 0;
             r = l, l = std::max(0, r - log10_base)) {
            int tmp = 0;
            for (int i = l; i < r; ++i) {
                tmp = tmp * 10 + (s[i] - '0');
            }
            v.push_back(tmp);
        }
    }

    BigInt& operator+=(const BigInt& rhs) {
        int r_sgn = rhs.sgn;
        if (r_sgn == 0) return *this;
        if (sgn == 0) return *this = rhs;
        if (v.size() < rhs.v.size()) v.resize(rhs.v.size(), 0);
        for (size_t i = 0; i < rhs.v.size(); i++) {
            if (sgn == r_sgn)
                v[i] += rhs.v[i];
            else
                v[i] -= rhs.v[i];
        }
        normalize();
        return *this;
    }
    BigInt& operator-=(const BigInt& rhs) {
        int r_sgn = rhs.sgn;
        if (r_sgn == 0) return *this;
        if (sgn == 0) return *this = -rhs;
        if (v.size() < rhs.v.size()) v.resize(rhs.v.size(), 0);
        for (size_t i = 0; i < rhs.v.size(); i++) {
            if (sgn == r_sgn)
                v[i] -= rhs.v[i];
            else
                v[i] += rhs.v[i];
        }
        normalize();
        return *this;
    }
    BigInt& operator*=(const BigInt& rhs) {
        int r_sgn = rhs.sgn;
        if (sgn == 0) return *this;
        if (r_sgn == 0) return *this = rhs;

        int res_sgn = sgn * r_sgn;

        if (int(std::min(v.size(), rhs.v.size())) <= naive_mul_threshold) {
            v = multiply_naive(v, rhs.v);
        } else if (std::max(v.size(), rhs.v.size()) > karatsuba_mul_threshold &&
                   v.size() + rhs.v.size() - 1 <= (1 << 24)) {
            v = multiply_ntt(v, rhs.v);
        } else {
            std::vector<long long> a(v.size()), b(rhs.v.size());
            for (size_t i = 0; i < a.size(); i++) {
                a[i] = (long long)v[i];
            }
            for (size_t i = 0; i < b.size(); i++) {
                b[i] = (long long)rhs.v[i];
            }
            int sz = 1;
            while (sz < int(a.size()) || sz < int(b.size())) sz *= 2;
            a.resize(sz, 0);
            b.resize(sz, 0);

            this->v = normalize(multiply_karatsuba(a, b));
        }

        this->sgn = res_sgn;

        return *this;
    }
    BigInt& operator/=(const BigInt& rhs) {
        int r_sgn = rhs.sgn;
        assert(r_sgn != 0);
        if (sgn == 0) return *this;
        if (rhs == BigInt(1) || rhs == BigInt(-1)) {
            sgn *= r_sgn;
            return *this;
        }

        int res_sgn = sgn * r_sgn;

        (*this) = divide_newton_raphson(*this, rhs);

        this->sgn = (this->v.back() == 0 ? 0 : res_sgn);

        return *this;
    }
    BigInt& operator%=(const BigInt& rhs) {
        assert(rhs.sgn != 0);

        return *this = (*this) - (*this) / rhs * rhs;
    }

    friend BigInt operator+(const BigInt& lhs, const BigInt& rhs) {
        return BigInt(lhs) += rhs;
    }
    friend BigInt operator-(const BigInt& lhs, const BigInt& rhs) {
        return BigInt(lhs) -= rhs;
    }
    friend BigInt operator*(const BigInt& lhs, const BigInt& rhs) {
        return BigInt(lhs) *= rhs;
    }
    friend BigInt operator/(const BigInt& lhs, const BigInt& rhs) {
        return BigInt(lhs) /= rhs;
    }
    friend BigInt operator%(const BigInt& lhs, const BigInt& rhs) {
        return BigInt(lhs) %= rhs;
    }

    BigInt operator+() const { return *this; }
    BigInt operator-() const { return {-sgn, v}; }

    BigInt& operator++() { return *this += 1; }
    BigInt& operator--() { return *this -= 1; }

    friend bool operator==(const BigInt& lhs, const BigInt& rhs) {
        if (lhs.sgn != rhs.sgn || lhs.v.size() != rhs.v.size()) return false;
        for (size_t i = 0; i < lhs.v.size(); i++) {
            if (lhs.v[i] != rhs.v[i]) return false;
        }
        return true;
    }
    friend bool operator!=(const BigInt& lhs, const BigInt& rhs) {
        return !(lhs == rhs);
    }
    friend bool operator<(const BigInt& lhs, const BigInt& rhs) {
        int l_sgn = lhs.sgn, r_sgn = rhs.sgn;
        if (l_sgn < r_sgn) return true;
        if (l_sgn > r_sgn) return false;

        int nl = lhs.v.size(), nr = rhs.v.size();
        if (l_sgn * nl < r_sgn * nr) return true;
        if (l_sgn * nl > r_sgn * nr) return false;

        for (int i = nl - 1; i >= 0; i--) {
            if (l_sgn * lhs.v[i] < r_sgn * rhs.v[i]) return true;
            if (l_sgn * lhs.v[i] > r_sgn * rhs.v[i]) return false;
        }

        return false;
    }
    friend bool operator>(const BigInt& lhs, const BigInt& rhs) {
        return rhs < lhs;
    }
    friend bool operator<=(const BigInt& lhs, const BigInt& rhs) {
        return !(lhs > rhs);
    }
    friend bool operator>=(const BigInt& lhs, const BigInt& rhs) {
        return rhs <= lhs;
    }

    friend std::istream& operator>>(std::istream& is, BigInt& rhs) {
        std::string s;
        is >> s;
        rhs = BigInt(s);
        return is;
    }
    friend std::ostream& operator<<(std::ostream& os, const BigInt& rhs) {
        if (rhs.sgn < 0) os << "-";
        for (int i = int(rhs.v.size()) - 1; i >= 0; i--) {
            if (i == int(rhs.v.size()) - 1) {
                os << rhs.v[i];
            } else {
                os << std::to_string(rhs.v[i] + base).substr(1, log10_base);
            }
        }
        return os;
    }

    operator double() const {
        double res = 0;
        for (int i = v.size() - 1; i >= 0; i--) {
            res = res * base + v[i];
        }
        res *= sgn;
        return res;
    }
    operator long double() const {
        long double res = 0;
        for (int i = v.size() - 1; i >= 0; i--) {
            res = res * base + v[i];
        }
        res *= sgn;
        return res;
    }

   private:
    static constexpr int base = 10000, log10_base = 4;
    static constexpr int naive_mul_threshold = 75,
                         karatsuba_mul_threshold = 4000;
    int sgn;
    std::vector<int> v;

    BigInt(int sgn, std::vector<int> v) : sgn(sgn), v(v) {}

    void normalize() {
        while (v.size() >= 2 && v.back() == 0) v.pop_back();

        if (v.back() < 0) {
            sgn = -sgn;
            std::transform(v.begin(), v.end(), v.begin(),
                           [](int x) { return -x; });
        }

        int carry = 0;
        for (size_t i = 0; i < v.size(); i++) {
            v[i] += carry;
            if (0 <= v[i] && v[i] < base) {
                carry = 0;
                continue;
            }
            carry = div_floor(v[i], base);
            v[i] -= carry * base;
        }
        while (carry > 0) {
            v.push_back(carry % base);
            carry /= base;
        }

        while (v.size() >= 2 && v.back() == 0) v.pop_back();
        if (v.size() == 1 && v[0] == 0) sgn = 0;
    }
    template <class T>
    static std::vector<int> normalize(const std::vector<T>& c) {
        std::vector<int> res(c.size());
        T carry = 0;
        for (size_t i = 0; i < c.size(); i++) {
            T tmp = c[i];
            tmp += carry;
            if (0 <= tmp && tmp < T(base)) {
                carry = 0;
                res[i] = int(tmp);
                continue;
            }
            carry = div_floor(tmp, T(base));
            res[i] = int(tmp - carry * base);
        }
        while (carry > 0) {
            res.push_back(int(carry % base));
            carry /= base;
        }

        while (res.size() >= 2 && res.back() == 0) res.pop_back();

        return res;
    }

    static std::vector<int> multiply_naive(const std::vector<int>& a,
                                           const std::vector<int>& b) {
        std::vector<long long> c(a.size() + b.size() - 1, 0);
        for (size_t i = 0; i < a.size(); i++) {
            for (size_t j = 0; j < b.size(); j++) {
                c[i + j] += a[i] * b[j];
            }
        }

        return normalize(c);
    }
    static std::vector<int> multiply_ntt(const std::vector<int>& a,
                                         const std::vector<int>& b) {
        std::vector<long long> al(a.size()), bl(b.size());
        for (size_t i = 0; i < a.size(); i++) {
            al[i] = (long long)a[i];
        }
        for (size_t i = 0; i < b.size(); i++) {
            bl[i] = (long long)b[i];
        }

        std::vector<long long> c = atcoder::convolution_ll(al, bl);

        return normalize(c);
    }
    static std::vector<long long> multiply_karatsuba(std::vector<long long> a,
                                                     std::vector<long long> b) {
        int na = a.size(), nb = b.size();
        if (std::min(na, nb) <= naive_mul_threshold) {
            std::vector<long long> res(a.size() + b.size() - 1, 0);
            for (size_t i = 0; i < a.size(); i++) {
                for (size_t j = 0; j < b.size(); j++) {
                    res[i + j] += a[i] * b[j];
                }
            }
            return res;
        }

        int n = std::max(na, nb);
        if (na < n) a.resize(n, 0);
        if (nb < n) b.resize(n, 0);

        int k = n / 2;
        std::vector<long long> x(
            std::vector<long long>(a.begin() + k, a.end()));
        std::vector<long long> y(
            std::vector<long long>(a.begin(), a.begin() + k));
        std::vector<long long> z(
            std::vector<long long>(b.begin() + k, b.end()));
        std::vector<long long> w(
            std::vector<long long>(b.begin(), b.begin() + k));

        std::vector<long long> xz = multiply_karatsuba(x, z);
        std::vector<long long> yw = multiply_karatsuba(y, w);

        for (int i = 0; i < k; i++) {
            x[i] += y[i];
            z[i] += w[i];
        }
        std::vector<long long> t = multiply_karatsuba(x, z);
        for (size_t i = 0; i < xz.size(); i++) {
            t[i] -= xz[i] + yw[i];
        }

        a = std::vector<long long>(2 * k, 0);
        a.insert(a.end(), xz.begin(), xz.end());
        b = std::vector<long long>(k, 0);
        b.insert(b.end(), t.begin(), t.end());

        for (size_t i = 0; i < b.size(); i++) {
            a[i] += b[i];
        }
        for (size_t i = 0; i < yw.size(); i++) {
            a[i] += yw[i];
        }

        return a;
    }

    static void shift_r(BigInt& a, size_t len) {
        if (a == BigInt(0)) return;
        if (a.v.size() <= len) {
            a = 0;
            return;
        }
        a.v.erase(a.v.begin(), a.v.begin() + len);
    }

    static BigInt divide_newton_raphson(BigInt a, BigInt b) {
        a.sgn = b.sgn = 1;
        if (a < b) return 0;
        size_t len = a.v.size() + 2;
        BigInt x = base * base, prv = x;
        while (true) {
            BigInt tmp = x * x * b;
            shift_r(tmp, len);
            x += x;
            x -= tmp;
            if (x.v.size() > len) shift_r(x, x.v.size() - len);

            if ((x - prv).v.size() <= 1) break;
            prv = x;
        }
        BigInt res = a * x;
        res.v.erase(res.v.begin(), res.v.begin() + len);
        if (res * b + b <= a) ++res;

        return res;
    }
};

}  // namespace rklib

using namespace rklib;

int main() {
    lint n;
    cin >> n;
    string str = to_string(n);
    BigInt N(str);
    for (string s = "9"; ; s += "9") {
        if (s.size() <= 18) {
            lint x = stoll(s);
            if (x % n == 0) {
                cout << s.size() << "\n";
                return 0;
            }
        } else {
            BigInt M(s);
            BigInt R = N % M;
            BigInt r("0");
            if (R == r) {
                cout << s.size() << "\n";
                return 0;
            }
        }
    }
}
0