QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#186381 | #6399. Classic: Classical Problem | ucup-team228# | WA | 5ms | 9712kb | C++20 | 8.2kb | 2023-09-23 18:58:20 | 2023-09-23 18:58:21 |
Judging History
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;
}
if (n == 1) {
cout << P << " 1\n";
for (int c = 0; c < P; ++c) {
cout << c << ' ';
}
cout << '\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;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 0ms
memory: 9676kb
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: 0
Accepted
time: 5ms
memory: 9712kb
input:
3 1 2 0 1 2 1 2 2 1 0
output:
2 1 0 1 1 1 0 1 2 1
result:
ok 6 lines
Test #3:
score: 0
Accepted
time: 2ms
memory: 9656kb
input:
7 1 3 0 1 3 1 2 3 1 0 1 3 2 2 3 2 0 2 3 1 2 3 3 0 1 2
output:
3 1 0 1 2 1 1 0 1 2 1 1 1 0 1 2 2 1 1 0 2 3 1 2
result:
ok 14 lines
Test #4:
score: -100
Wrong Answer
time: 5ms
memory: 9664kb
input:
31 1 5 0 1 5 1 2 5 1 0 1 5 2 2 5 0 2 2 5 2 1 3 5 1 0 2 1 5 3 2 5 0 3 2 5 1 3 3 5 0 1 3 2 5 3 2 3 5 0 2 3 3 5 2 1 3 4 5 2 0 1 3 1 5 4 2 5 4 0 2 5 1 4 3 5 1 4 0 2 5 2 4 3 5 2 4 0 3 5 4 2 1 4 5 1 0 4 2 2 5 4 3 3 5 0 4 3 3 5 3 1 4 4 5 1 4 3 0 3 5 4 3 2 4 5 2 4 0 3 4 5 2 1 4 3 5 5 1 3 0 2 4
output:
5 1 0 1 2 3 4 1 1 0 1 2 1 1 1 0 1 2 2 1 1 0 1 3 1 1 1 0 1 2 3 1 1 0 1 3 3 1 1 0 2 2 2 3 1 1 0 1 4 1 1 1 0 1 2 4 1 1 0 2 2 1 4 1 1 0 1 3 2 1 1 0 1 4 2 1 1 0 1 3 4 1 1 0 1 4 3 1 1 0 1 4 4 1 1 0 4 5 1 2 3 4
result:
wrong answer 10th lines differ - expected: '3', found: '2 '