QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#186377#6399. Classic: Classical Problemucup-team228#WA 5ms9780kbC++208.0kb2023-09-23 18:51:022023-09-23 18:51:03

Judging History

你现在查看的是最新测评结果

  • [2023-09-23 18:51:03]
  • 评测
  • 测评结果:WA
  • 用时:5ms
  • 内存:9780kb
  • [2023-09-23 18:51:02]
  • 提交

answer

#include <bits/stdc++.h>

using namespace std;

#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()

typedef long long ll;
typedef pair<int, int> pii;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

template<typename T>
std::ostream& operator << (std::ostream& os, const vector<T>& a) {
    for (const T& x : a) {
        os << x << ' ';
    }
    return os;
}

template <int m>
struct mint {
    int x = 0;
    mint(int64_t a = 0) { if (a < 0) a = a % m + m; if (a >= m) a %= m; x = a; }
    friend istream& operator>>(istream& in, mint& a) { int64_t y; in >> y; a = y; return in; }
    friend ostream& operator<<(ostream& out, mint a) { return out << a.x; }
    explicit operator int() const { return x; }
    static int mod_inv(int a, int mod = m) {
        int g = mod, r = a, z = 0, y = 1;
        while (r != 0) { int q = g / r; g %= r; swap(g, r); z -= q * y; swap(z, y); }
        return z < 0 ? z + mod : z;
    }
    mint inv() const { return mod_inv(x, m); }
    friend mint binpow(mint a, int64_t b) { mint res = 1; while (b) { if (b & 1) res *= a; b >>= 1; a *= a; } return res; }
    mint pow(int64_t b) const { return binpow(*this, b); }
    mint operator-() const { return x ? m - x : 0; }
    mint& operator+=(const mint& a) { x += a.x; if (x >= m) x -= m; return *this; }
    mint& operator-=(const mint& a) { x -= a.x; if (x < 0) x += m; return *this; }
    static unsigned fast_mod(uint64_t x, unsigned mod = m) {
#if defined(_WIN32) && !defined(_WIN64)
        // Optimized mod for Codeforces 32-bit machines.
        // x must be less than 2^32 * mod for this to work, so that x / mod fits in a 32-bit integer.
        unsigned x_high = x >> 32, x_low = (unsigned) x; unsigned quot, rem;
        asm("divl %4\n" : "=a" (quot), "=d" (rem) : "d" (x_high), "a" (x_low), "r" (mod));
        return rem;
#else
        return x % mod;
#endif
    }
    mint& operator*=(const mint& a) { x = fast_mod((uint64_t) x * a.x); return *this; }
    mint& operator/=(const mint& a) { return *this *= a.inv(); }
    friend mint operator+(mint a, const mint& b) { return a += b; }
    friend mint operator-(mint a, const mint& b) { return a -= b; }
    friend mint operator*(mint a, const mint& b) { return a *= b; }
    friend mint operator/(mint a, const mint& b) { return a /= b; }
    mint& operator++() { x = x == m - 1 ? 0 : x + 1; return *this; }
    mint& operator--() { x = x == 0 ? m - 1 : x - 1; return *this; }
    mint operator++(int) { mint a = *this; ++*this; return a; }
    mint operator--(int) { mint a = *this; --*this; return a; }
    bool operator==(const mint& a) const { return x == a.x; }
    bool operator!=(const mint& a) const { return x != a.x; }
};

const int mod = 985661441;
const int K = 1 << 20; // be careful
const mint<mod> root = binpow(mint<mod>(3), (mod - 1) / K); 
// 3 is a primitive root modulo mod

typedef vector<mint<mod>> poly;

mint<mod> prec_w[K / 2];
mint<mod> w[K];

bool initialized = 0;
void init() {
    if (initialized) {
        return;
    }
    initialized = 1;
    prec_w[0] = 1;
    for (int i = 1; i < K / 2; i++) {
        prec_w[i] = prec_w[i - 1] * root;
    }
    for (int i = 1; i < K; i *= 2) {
        for (int j = 0; j < i; j++) {
            w[i + j] = prec_w[K / (2 * i) * j];
        }
    }
}

void fft(mint<mod>* in, mint<mod>* out, int n, int k = 1) {
    if (n == 1) {
        *out = *in;
        return;
    }
    n /= 2;
    fft(in, out, n, 2 * k);
    fft(in + k, out + n, n, 2 * k);
    for (int i = 0; i < n; i++) {
        mint<mod> t = out[i + n] * w[i + n];
        out[i + n] = out[i] - t;
        out[i] += t;
    }
}

void align(poly& a, poly& b) {
    int n = a.size() + b.size() - 1;
    while (a.size() < n) a.push_back(0);
    while (b.size() < n) b.push_back(0);
}

poly eval(poly& a) {
    while (__builtin_popcount(a.size()) != 1) {
        a.push_back(0);
    }
    poly res(a.size());
    fft(a.data(), res.data(), a.size());
    return res;
}

poly inter(poly a) {
    int n = a.size();
    poly res(n);
    fft(a.data(), res.data(), n);
    for (int i = 0; i < n; i++) {
        res[i] /= n;
    }
    reverse(res.begin() + 1, res.end());
    return res;
}

poly mult(poly a, poly b) {
    init();
    align(a, b);
    a = eval(a);
    b = eval(b);
    for (int i = 0; i < a.size(); i++) {
        a[i] *= b[i];
    }
    a = inter(a);
    return a;
}

int mult(int a, int b, int MOD) {
    return (a * 1LL * b) % MOD;
}
int bin_pow(int a, int n, int MOD) {
    int res = 1;
    for (; n; n >>= 1, a = mult(a, a, MOD)) {
        if (n & 1) {
            res = mult(res, a, MOD);
        }
    }
    return res;
}

using Mint = mint<mod>;

vector<int> get_primes(int n) {
    vector<int> res;
    for (int d = 2; d * d <= n; ++d) {
        if (n % d == 0) {
            res.push_back(d);
            while (n % d == 0) {
                n /= d;
            }
        }
    }
    if (n > 1) {
        res.push_back(n);
    }
    return res;
}

bool check_primitive_root(int g, int P) {
    vector<int> prime_divs = get_primes(P - 1);
    for (int p : prime_divs) {
        if (bin_pow(g, (P - 1) / p, P) == 1) {
            return false;
        }
    }
    return true;
}

int get_primitive_root(int P) {
    int g = 2;
    while (!check_primitive_root(g, P)) {
        ++g;
    }
    //cout << g << '\n';
    return g;
}

void solve() {
    int n, P;
    cin >> n >> P;
    int g = get_primitive_root(P);

    vector<int> log_g(P);
    vector<int> pw_g(P - 1);
    for (int i = 0, power = 1; i < P - 1; ++i, power = mult(power, g, P)) {
        //cout << power << ' ' << i << '\n';
        pw_g[i] = power;
        log_g[power] = i;
    }
    //cout << endl;

    vector<Mint> a(P - 1);
    bool zero = false;
    for (int i = 0; i < n; ++i) {
        int y;
        cin >> y;
        if (y == 0) {
            zero = true;
            continue;
        }
        a[log_g[y]] = 1;
    }

    if (!zero) {
        cout << "1 1\n";
        cout << "0\n";
        return;
    }

    for (int i = 0; i < P - 1; ++i) {
        a.push_back(a[i]);
    }
    //cout << a << endl;
    int k = 0;
    while ((1 << k) < 3 * (P - 1)) {
        ++k;
    }
    int N = 1 << k;

    /*
    vector<Mint> res_a(N);
    while (a.size() < N) {
        a.push_back(0);
    }
    fft(a.data(), res_a.data(), N);
    */

    vector<int> out;

    auto check = [&](int mid) {
        out.clear();
        //cout << "mid = " << mid << endl;

        vector<Mint> b(P - 1);
        for (int x = 1; x <= mid; ++x) {
            b[log_g[x]] = 1;
        }
        //cout << b << '\n';
        reverse(all(b));
        /*
        while (b.size() < N) {
            b.push_back(0);
        }
        */
        //cout << a << '\n';
        //cout << b << '\n';
        /*
        vector<Mint> res_b(N);
        fft(b.data(), res_b.data(), N);
        for (int i = 0; i < N; ++i) {
            res_a[i] *= res_b[i];
        }

        vector<Mint> res = inter(res_a);
        */
        auto res = mult(a, b);
        //cout << res << '\n';

        bool ok = false;
        for (int i = P - 2; i <= 2 * (P - 2); ++i) {
            if (res[i] == mid) {
                out.push_back(i - (P - 2));
                ok = true;
            }
        }

        return ok;
    };

    int low = 0, high = P;
    while (high - low > 1) {
        int mid = (low + high) / 2;
        if (check(mid)) {
            low = mid;
        } else {
            high = mid;
        }
    }

    check(low);

    cout << out.size() << ' ' << low + 1 << '\n';
    vector<int> output;
    for (int c : out) {
        output.push_back(pw_g[c]);
    }
    sort(all(output));
    cout << output << '\n';
}

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

    init();

    int t;
    cin >> t;
    while (t--) {
        solve();
    }

    return 0;
}

詳細信息

Test #1:

score: 100
Accepted
time: 0ms
memory: 9748kb

input:

3
2 3
0 2
3 5
2 3 4
3 5
0 2 3

output:

1 2
2 
1 1
0
2 2
2 3 

result:

ok 6 lines

Test #2:

score: -100
Wrong Answer
time: 5ms
memory: 9780kb

input:

3
1 2
0
1 2
1
2 2
1 0

output:

1 1
1 
1 1
0
1 2
1 

result:

wrong answer 1st lines differ - expected: '2 1', found: '1 1'