QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#178386 | #6399. Classic: Classical Problem | ucup-team1600# | WA | 1ms | 3524kb | C++20 | 9.9kb | 2023-09-13 22:24:06 | 2023-09-13 22:24:07 |
Judging History
answer
//#pragma GCC optimize("Ofast", "unroll-loops")
//#pragma GCC target("sse", "sse2", "sse3", "ssse3", "sse4")
#ifdef LOCAL
#include <iostream>
#include <cmath>
#include <algorithm>
#include <stdio.h>
#include <cstdint>
#include <cstring>
#include <string>
#include <cstdlib>
#include <vector>
#include <bitset>
#include <map>
#include <queue>
#include <ctime>
#include <stack>
#include <set>
#include <list>
#include <random>
#include <deque>
#include <functional>
#include <iomanip>
#include <sstream>
#include <fstream>
#include <complex>
#include <numeric>
#include <cassert>
#include <array>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <thread>
#else
#include <bits/stdc++.h>
#endif
#define all(a) a.begin(),a.end()
#define len(a) (int)(a.size())
#define mp make_pair
#define pb push_back
#define fir first
#define sec second
#define fi first
#define se second
using namespace std;
typedef pair<int, int> pii;
typedef long long ll;
typedef long double ld;
template<typename T>
inline bool umin(T &a, T b) {
if (b < a) {
a = b;
return true;
}
return false;
}
template<typename T>
inline bool umax(T &a, T b) {
if (a < b) {
a = b;
return true;
}
return false;
}
#ifdef LOCAL
#define D for (bool _FLAG = true; _FLAG; _FLAG = false)
#define LOG(...) print(#__VA_ARGS__" ::", __VA_ARGS__) << endl
template <class ...Ts> auto &print(Ts ...ts) { return ((cerr << ts << " "), ...); }
#else
#define D while (false)
#define LOG(...)
#endif // LOCAL
const int max_n = -1, inf = 1000111222;
int powmod (int a, int b, int p) {
int res = 1;
while (b)
if (b & 1)
res = int (res * 1ll * a % p), --b;
else
a = int (a * 1ll * a % p), b >>= 1;
return res;
}
int generator (int p) {
vector<int> fact;
int phi = p-1, n = phi;
for (int i=2; i*i<=n; ++i)
if (n % i == 0) {
fact.push_back (i);
while (n % i == 0)
n /= i;
}
if (n > 1)
fact.push_back (n);
for (int res=2; res<=p; ++res) {
bool ok = true;
for (size_t i=0; i<fact.size() && ok; ++i)
ok &= powmod (res, phi / fact[i], p) != 1;
if (ok) return res;
}
return -1;
}
const int MOD = 998244353;
struct mint {
int val;
mint () : val(0) {}
mint (int x) {
if (-MOD <= x && x < MOD) {
val = x;
}
else {
val = x % MOD;
}
if (val < 0) val += MOD;
}
mint (ll x) {
if (-MOD <= x && x < MOD) {
val = x;
}
else {
val = x % MOD;
}
if (val < 0) val += MOD;
}
mint (const mint& x) : val(x.val) {}
constexpr mint& operator = (const mint& x) {
val = x.val;
return *this;
}
inline mint& operator += (const mint &x) {
val += x.val;
if (val >= MOD) {
val -= MOD;
}
return *this;
}
inline mint& operator -= (const mint &x) {
val -= x.val;
if (val < 0) {
val += MOD;
}
return *this;
}
inline mint operator - () const {
mint tmp(*this);
if (tmp.val) tmp.val = MOD - tmp.val;
return tmp;
}
inline mint operator + (const mint &x) const {
return mint(*this) += x;
}
inline mint operator - (const mint &x) const {
return mint(*this) -= x;
}
inline mint& operator *= (const mint &x) {
val = ((ll)val * x.val) % MOD;
return *this;
}
inline mint operator * (const mint &x) const {
return mint(*this) *= x;
}
inline mint binpow (int n) const {
mint res = 1, tmp = *this;
for (; n; n >>= 1) {
if (n & 1) {
res *= tmp;
}
tmp *= tmp;
}
return res;
}
inline mint inverse () const {
return binpow(MOD - 2);
}
inline mint& operator /= (const mint &x) {
return *this *= x.inverse();
}
inline mint operator / (const mint &x) {
return mint(*this) *= x.inverse();
}
friend ostream& operator << (ostream &os, const mint &x) {
os << x.val;
return os;
}
friend istream& operator >> (istream &is, mint &x) {
is >> x.val;
return is;
}
inline bool operator == (const mint &x) const {
return val == x.val;
}
inline bool operator != (const mint &x) const {
return val != x.val;
}
inline bool operator < (const mint &x) const {
return val < x.val;
}
inline bool operator > (const mint &x) const {
return val > x.val;
}
friend string to_string (const mint &x) {
return to_string(x.val);
}
};
vector <mint> f = {1}, fi = {1};
inline mint fact (int n) {
f.reserve(n + 1);
while (len(f) <= n) {
f.emplace_back(f.back() * len(f));
}
return f[n];
}
inline mint inv_fact (int n) { /// think
if (len(fi) <= n) {
fi.resize(n + 1, 0);
mint val = mint(1) / fact(n);
for (int i = n; fi[i] == 0; i--) {
fi[i] = val;
val *= i;
}
}
return fi[n];
}
inline mint A (int n, int k) {
if (k < 0 || k > n) return 0;
return fact(n) * inv_fact(n - k);
}
inline mint C (int n, int k) {
if (k < 0 || k > n) return 0;
return A(n, k) * inv_fact(k);
}
typedef vector<mint> poly;
const mint PRIMITIVE_ROOT = 3; /// 119 * 2^23 + 1
vector <int> rev;
vector <mint> roots, inv_roots, cur, ncur;
inline void calc_rev (int n) {
if (len(rev) == n) return;
rev.clear();
int k = 0;
while ((1 << k) < n) k++;
rev.resize(n);
rev[0] = 0;
int high1 = -1;
for (int i = 1; i < n; i++) {
if ((i & (i - 1)) == 0) high1++;
rev[i] = rev[i ^ (1 << high1)];
rev[i] |= (1 << (k - high1 - 1));
}
mint W = PRIMITIVE_ROOT.binpow((MOD - 1) / n);
mint W1 = W.inverse();
roots.clear();
roots.reserve(25);
inv_roots.clear();
inv_roots.reserve(25);
for (int len = 1; len < n; len <<= 1) {
roots.pb(W);
inv_roots.pb(W1);
W *= W;
W1 *= W1;
}
reverse(all(roots));
reverse(all(inv_roots));
cur.clear();
ncur.clear();
cur.resize(n);
ncur.resize(n);
}
poly fft(const poly &as, bool inv = false) {
/// source: https://pastebin.com/3Tnj5mRu
int n = as.size();
calc_rev(n);
for (int i = 0; i < n; i++) cur[i] = as[rev[i]];
for (int len = 1, l = 0; len < n; len <<= 1, l++) {
mint w_n = inv ? inv_roots[l] : roots[l], w;
for (int pdest = 0; pdest < n;) {
int p1 = pdest;
w = 1;
for (int i = 0; i < len; i++) {
mint val = w * cur[p1 + len];
ncur[pdest] = cur[p1] + val;
ncur[pdest + len] = cur[p1] - val;
pdest++, p1++;
w *= w_n;
}
pdest += len;
}
cur.swap(ncur);
}
return cur;
}
poly fft_rev(const poly &as) {
poly res = fft(as, true);
mint inv = mint(1) / mint(len(as));
for (int i = 0; i < (int)res.size(); i++) res[i] *= inv;
// reverse(res.begin() + 1, res.end());
return res;
}
inline poly multiply (poly A, poly B) {
int n = max(len(A), len(B));
int k = 0;
while ((1 << k) < n) ++k;
++k;
k = 1 << k;
A.resize(k);
B.resize(k);
A = fft(A);
B = fft(B);
for (int i = 0; i < k; i++) {
A[i] *= B[i];
}
return fft_rev(A);
}
inline void test_case () {
int n, p;
cin >> n >> p;
vector <int> a(n);
bool ok = false;
for (int i = 0; i < n; i++) {
cin >> a[i];
if (a[i] == 0) {
ok = true;
}
}
if (!ok) {
cout << "1 1\n0\n";
return;
}
int root = generator(p);
vector <int> b(p);
for (int i = 1, c = 0; c + 1 < p; c++) {
b[i] = c;
i = (i * 1ll * root) % p;
}
vector <mint> have(p);
for (int i = 0; i < n; i++) {
if (a[i] == 0) {
continue;
}
have[b[a[i]]] = 1;
}
int l = 1, r = p;
while (l < r) {
int mid = (l + r + 1) >> 1;
vector <mint> cur(p);
for (int i = 1; i < mid; i++) {
cur[p - 1 - b[i]] = 1;
}
auto res = multiply(cur, have);
bool can = false;
for (int c = 0; c < p - 1; c++) {
int val = res[c].val + res[c + (p - 1)].val;
if (val + 1 == mid) {
can = true;
}
}
if (can) {
l = mid;
}
else {
r = mid - 1;
}
}
vector <mint> cur(p);
for (int i = 1; i < r; i++) {
cur[p - 1 - b[i]] = 1;
}
auto res = multiply(cur, have);
vector <int> ans;
bool can = false;
int gg = root;
for (int c = p - 2; c >= 0; c--) {
int val = res[c].val + res[c + (p - 1)].val;
if (val + 1 == r) {
ans.pb(gg);
}
gg = (gg * 1ll * root) % p;
}
if (r == 1) {
ans.pb(0);
}
cout << len(ans) << ' ' << r << '\n';
sort(all(ans));
for (auto &i : ans) {
cout << i << ' ';
}
cout << '\n';
}
int main() {
// freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int t = 1;
cin >> t;
for (int test = 1; test <= t; test++) {
test_case();
}
}
详细
Test #1:
score: 100
Accepted
time: 1ms
memory: 3420kb
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: 0ms
memory: 3524kb
input:
3 1 2 0 1 2 1 2 2 1 0
output:
2 1 0 2 1 1 0 1 2 2
result:
wrong answer 2nd lines differ - expected: '0 1', found: '0 2 '