algo — C++23 日本語リファレンス GitHub

test/aoj/challenge/3002.test.cpp

AC · 最終更新 2026-09-06 · GitHub

問題: https://onlinejudge.u-aizu.ac.jp/problems/3002

依存するヘッダ(1)
実装
// competitive-verifier: PROBLEM https://onlinejudge.u-aizu.ac.jp/problems/3002
#include <algorithm>
#include <cctype>
#include <iostream>
#include <string>
#include <vector>
#include "parser/parser.hpp"

// Factorization: モニックな n 次多項式 (2≤n≤5) を相異なる整数根の一次式の積に
// 因数分解する。値型を多項式にした ExpressionParser で式を評価し、根は定数項の
// 約数に限られるので全探索。一次式 (x-r) を定数項 -r の昇順で出力。
// 項 = [係数] x [^指数] | 定数 をアトムで、+ - を二項演算子で扱う。
using ll = long long;
using Poly = std::vector<ll>;  // 添字 = 次数
using P = ExpressionParser<Poly>;

static Poly comb(const Poly &a, const Poly &b, int sign) {
    Poly r(std::max(a.size(), b.size()), 0);
    for (std::size_t i = 0; i < a.size(); ++i) r[i] += a[i];
    for (std::size_t i = 0; i < b.size(); ++i) r[i] += sign * b[i];
    return r;
}

int main() {
    P p;
    p.binary("+", 10, P::Assoc::Left, [](const Poly &a, const Poly &b) { return comb(a, b, 1); })
        .binary("-", 10, P::Assoc::Left, [](const Poly &a, const Poly &b) { return comb(a, b, -1); })
        .atom([](P &q) -> Poly {
            ll coef = 1;
            if (std::isdigit((unsigned char)q.peek())) coef = q.read_uint();
            int exp = 0;
            if (q.peek() == 'x') {
                q.advance();
                exp = 1;
                if (q.peek() == '^') q.advance(), exp = (int)q.read_uint();
            }
            Poly r(exp + 1, 0);
            r[exp] = coef;
            return r;
        });

    std::string s;
    while (std::getline(std::cin, s)) {
        if (s.empty()) continue;
        Poly f = p.parse(s);
        ll a0 = f[0];
        // 整数根は定数項の約数。各根 r に対し一次式 (x-r) の定数項は -r。
        std::vector<ll> consts;  // 各因子の定数項 (= -root)
        for (ll r = -std::abs(a0); r <= std::abs(a0); ++r) {
            if (r == 0 || a0 % r != 0) continue;
            __int128 v = 0;
            for (int i = (int)f.size() - 1; i >= 0; --i) v = v * r + f[i];
            if (v == 0) consts.push_back(-r);
        }
        std::sort(consts.begin(), consts.end());
        for (ll c : consts) std::cout << (c < 0 ? "(x-" + std::to_string(-c) : "(x+" + std::to_string(c)) << ')';
        std::cout << '\n';
    }
    return 0;
}