Solving Polynomial Equations with Modular Arithmetic

Rewriting the Polynomial

Directly solving high-degree polynomials is computationally infeasible due to the lack of general root-finding formulas. Instead, we restructure the expression by factoring out terms:

Modular Evaluation Strategy

To verify whether a value of x satisfies the equation, we evaluate \(f(x) \bmod p\), where p is a large prime number (e.g., 998244353377). If the result is zero, it's highly probable that x is indeed a solution.

Implementation Approach

The rewritten polynomail can be evaluated efficiently from the innermost term outward. Here’s how this looks in code:

long long evaluate(long long x, const vector<long long>& coefficients, long long mod) {
    long long result = 0;
    int size = coefficients.size();
    
    // Evaluate from highest degree downward
    for (int i = size - 1; i > 0; --i) {
        result = ((coefficients[i] + result) * x) % mod;
    }
    
    // Add constant term
    result = (coefficients[0] + result) % mod;
    return result;
}

We then iterate through each candidate value of x between 1 and m, checking if the modular result equals zero:

vector<long long> solutions;
for (long long x = 1; x <= m; ++x) {
    if (evaluate(x, coefficients, MOD) == 0) {
        solutions.push_back(x);
    }
}

Handling Large Coefficients

Since coefficients may reach magnitudes up to \(10^{10000}\), standard integer types will overflow. To address this, we apply modular reduction during input processing:

// During coefficient reading
coefficients[i] %= MOD;

Complete Solution Example

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

typedef long long ll;
const ll MOD = 998244353377LL;

ll mod_input() {
    string s;
    cin >> s;
    ll val = 0;
    bool negative = false;
    int start = 0;
    
    if (s[0] == '-') {
        negative = true;
        start = 1;
    }
    
    for (int i = start; i < s.length(); ++i) {
        val = (val * 10 + (s[i] - '0')) % MOD;
    }
    
    return negative ? (-val % MOD + MOD) % MOD : val;
}

ll horner_eval(const vector<ll>& coeffs, ll x) {
    ll res = 0;
    for (int i = coeffs.size() - 1; i > 0; --i) {
        res = ((coeffs[i] + res) * x) % MOD;
    }
    return (coeffs[0] + res) % MOD;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, m;
    cin >> n >> m;
    
    vector<ll> coefficients(n + 1);
    for (int i = 0; i <= n; ++i) {
        coefficients[i] = mod_input();
    }

    vector<ll> results;
    for (int x = 1; x <= m; ++x) {
        if (horner_eval(coefficients, x) == 0) {
            results.push_back(x);
        }
    }

    cout << results.size() << "\n";
    for (ll sol : results) {
        cout << sol << "\n";
    }

    return 0;
}

This approach ensures both performance efficiency and numerical stability when dealing with extremely large inputs.

Tags: polynomial-equations modular-arithmetic horner-method number-theory C++

Posted on Wed, 21 Oct 2026 16:27:54 +0000 by jwk811