QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#547973 | #8305. Accelerator | haze# | WA | 249ms | 44504kb | C++23 | 11.9kb | 2024-09-05 14:16:37 | 2024-09-05 14:16:37 |
Judging History
answer
#include <cstdio>
#include <bits/stdc++.h>
const int maxn = 3e6 + 5, mod = 998244353;
template<typename T>
inline T max(const T &a, const T &b) {
return a > b ? a : b;
}
template<typename T>
inline void swap(T &a, T &b) {
T temp = a;
a = b;
b = temp;
}
struct IO {
IO() {};
char c;
inline char gc() {
static char buf[maxn], *p1 = buf, *p2 = buf;
return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, maxn, stdin), p1 == p2) ? EOF : *p1++;
}
template<typename T>
inline IO &operator>>(T &_) {
_ = 0;
bool f = 1;
c = gc();
while (c < '0' || c > '9') {
if (c == '-') f = 0;
c = gc();
}
while (c >= '0' && c <= '9') {
_ = _ * 10 + c - 48;
c = gc();
}
if (!f) _ = -_;
return *this;
}
char buf[maxn];
int p = 0;
~IO() { fwrite(buf, 1, p, stdout); }
inline void pc(const char &c) {
buf[p++] = c;
if (p == maxn) fwrite(buf, 1, maxn, stdout), p = 0;
}
template<typename T>
inline IO &operator<<(T x) {
if (!x) {
pc(48);
return *this;
}
static int wt[41], len;
len = 0;
if (x < 0) {
pc('-');
x = -x;
}
for (; x; x /= 10) { wt[++len] = x % 10; }
while (len) { pc(wt[len--] + 48); }
return *this;
}
inline IO &operator<<(const char &c) {
pc(c);
return *this;
}
} io;
int fastpow(int x, int y) {
if (y == 0) return 1;
int tmp = fastpow(x, y >> 1);
return y & 1 ? 1ll * tmp * tmp % mod * x % mod : 1ll * tmp * tmp % mod;
}
inline int add(int x, int y) { return x + y >= mod ? x + y - mod : x + y; }
inline int sub(int x, int y) { return x - y < 0 ? x - y + mod : x - y; }
inline void copy(int *Alpha, int *Beta, int len) {
//Alpha -> Beta
for (int i = 0; i < len; i++) Alpha[i] = Beta[i];
}
namespace Poly {
const int gate = 3, invg = fastpow(gate, mod - 2);
int lim, lg, sing[maxn];
int Gate[maxn], Invg[maxn];
int inv[maxn];
void init(int len) {
lim = 1, lg = 0;
while (lim < len) lim <<= 1, lg++;
for (int i = 1; i < lim; i++) sing[i] = (sing[i >> 1] >> 1) | ((i & 1) << (lg - 1));
}
int Hacking_to_the() {
for (int i = 1; i < maxn; i <<= 1)
Gate[i] = fastpow(gate, (mod - 1) / (i << 1)), Invg[i] = fastpow(invg, (mod - 1) / (i << 1));
// inv[1] = 1 ;for(int i=2;i<maxn;i++) inv[i] = (mod-1ll*(mod/i)*inv[mod%i]%mod) ;
return 0;
}
int GATE = Hacking_to_the();
void NTT(int *Steins, int type) {
for (int i = 0; i < lim; i++) if (i < sing[i]) swap(Steins[i], Steins[sing[i]]);
for (int len = 1; len < lim; len <<= 1) {
int unit = type == 1 ? Gate[len] : Invg[len];
for (int i = 0; i < lim; i += (len << 1)) {
int w = 1;
for (int k = 0; k < len; k++, w = 1ll * w * unit % mod) {
int x = Steins[i + k], y = 1ll * w * Steins[i + k + len] % mod;
Steins[i + k] = add(x, y), Steins[i + k + len] = sub(x, y);
}
}
}
if (type != 1) {
int Okabe = fastpow(lim, mod - 2);
for (int i = 0; i < lim; i++) Steins[i] = 1ll * Steins[i] * Okabe % mod;
}
}
void convolution(int *Alpha, int la, int *Beta, int lb, int *Zeta) {
init(la + lb - 1);
for (int i = la; i < lim; i++) Alpha[i] = 0;
for (int i = lb; i < lim; i++) Beta[i] = 0;
NTT(Alpha, 1), NTT(Beta, 1);
for (int i = 0; i < lim; i++) Zeta[i] = 1ll * Alpha[i] * Beta[i] % mod;
return NTT(Zeta, -1);
}
int g[maxn];
void get_inv(int *Alpha, int len, int *Beta) {
//使用前清空Beta数组
if (len == 1) {
Beta[0] = fastpow(Alpha[0], mod - 2);
return;
}
get_inv(Alpha, (len + 1) >> 1, Beta);
init(len + len - 1);
copy(g, Alpha, len);
for (int i = len; i < lim; i++) g[i] = 0;
NTT(Beta, 1), NTT(g, 1);
for (int i = 0; i < lim; i++) Beta[i] = 1ll * Beta[i] * (mod + 2 - 1ll * Beta[i] * g[i] % mod) % mod;
NTT(Beta, -1);
for (int i = len; i < lim; i++) Beta[i] = 0;
}
const int inv2 = fastpow(2, mod - 2);
int t[maxn];
void get_sqrt(int *Alpha, int len, int *Beta) {
//使用前清空Beta数组
if (len == 1) {
Beta[0] = 1;
return;
}
get_sqrt(Alpha, (len + 1) >> 1, Beta);
get_inv(Beta, len, t);
init(len + len - 1);
copy(g, Alpha, len);
for (int i = len; i < lim; i++) g[i] = 0;
convolution(g, len, t, len, g);
for (int i = 0; i < lim; i++) Beta[i] = 1ll * inv2 * (Beta[i] + g[i]) % mod;
for (int i = len; i < lim; i++) Beta[i] = 0;
for (int i = 0; i < lim; i++) t[i] = 0;
}
void derivative(int *Alpha, int len, int *Beta) {
for (int i = 1; i < len; i++) Beta[i - 1] = 1ll * i * Alpha[i] % mod;
Beta[len - 1] = 0;
}
void integral(int *Alpha, int len, int *Beta) {
for (int i = len - 1; i >= 1; i--) Beta[i] = 1ll * Alpha[i - 1] * inv[i];
Beta[0] = 0;
}
int f1[maxn], f2[maxn];
void get_ln(int *Alpha, int len, int *Beta) {
memset(f2, 0, sizeof(f2));
derivative(Alpha, len, f1), get_inv(Alpha, len, f2);
convolution(f1, len, f2, len, Beta);
return integral(Beta, len, Beta);
}
int e1[maxn], e2[maxn];
void get_exp(int *Alpha, int len, int *Beta) {
//使用前清空Beta数组
if (len == 1) return void(Beta[0] = 1);
get_exp(Alpha, (len + 1) >> 1, Beta);
get_ln(Beta, len, e1);
init(len + len - 1);
for (int i = 0; i < len; i++) e2[i] = sub(Alpha[i], e1[i]);
for (int i = len; i < lim; i++) e2[i] = 0;
NTT(e2, 1), NTT(Beta, 1);
for (int i = 0; i < lim; i++) Beta[i] = 1ll * Beta[i] * (e2[i] + 1) % mod;
NTT(Beta, -1);
for (int i = len; i < lim; i++) Beta[i] = 0;
for (int i = 0; i < lim; i++) e1[i] = 0;
}
int g1[maxn], g2[maxn], g3[maxn];
void division(int *Alpha, int la, int *Beta, int lb, int *Zeta, int *Gamma) {
//Zeta's length requires 2la-lb
if (la < lb) {
for (int i = 0; i <= la - lb; i++) Zeta[i] = 0;
for (int i = la; i < lb; i++) Gamma[i] = 0;
return copy(Gamma, Alpha, la);
}
for (int i = 0; i < la; i++) g1[i] = Alpha[la - i - 1];
for (int i = 0; i < lb; i++) g2[i] = Beta[lb - i - 1];
for (int i = lb; i <= la - lb; i++) g2[i] = 0;
lim = 1;
while (lim <= (la - lb) << 1) lim <<= 1;
for (int i = 0; i < lim; i++) g3[i] = 0;
get_inv(g2, la - lb + 1, g3);
convolution(g1, la, g3, la - lb + 1, Zeta);
for (int i = 0; i < la - lb - i; i++) swap(Zeta[i], Zeta[la - lb - i]);
for (int i = la - lb + 1; i < lim; i++) Zeta[i] = 0;
copy(g1, Beta, lb);
copy(g2, Zeta, la - lb + 1);
convolution(g1, lb, g2, la - lb + 1, g1);
for (int i = 0; i < lb; i++) Gamma[i] = sub(Alpha[i], g1[i]);
}
}
namespace Multi_point {
int *gate[maxn << 2];
void init(int now, int l, int r, int *Alpha) {
if (l == r) {
gate[now] = new int[2];
gate[now][0] = mod - Alpha[l], gate[now][1] = 1;
return;
}
int mid = (l + r) >> 1, lim = 1;
while (lim < r - l + 1 + 1) lim <<= 1;
gate[now] = new int[lim];
int *g1 = new int[lim], *g2 = new int[lim];
init(now << 1, l, mid, Alpha), init(now << 1 | 1, mid + 1, r, Alpha);
copy(g1, gate[now << 1], mid - l + 1 + 1);
copy(g2, gate[now << 1 | 1], r - mid + 1);
return Poly::convolution(g1, mid - l + 1 + 1, g2, r - mid + 1, gate[now]);
}
void evaluation(int now, int l, int r, int *Alpha, int *Beta, int *Zeta) {
//Alpha->f(x),Beta->S{x}
if (r - l + 1 <= 256) {
for (int i = l; i <= r; i++) {
int answer = 0;
int base = 1;
for (int j = 0; j <= r - l; j++, base = 1ll * base * Beta[i] % mod)
answer = (answer + 1ll * base * Alpha[j]) % mod;
Zeta[i] = answer;
}
return;//Which makes it faster;
}
int mid = (l + r) >> 1, lim = 1;
while (lim < r - l + 1 + 1) lim <<= 1;
int *g1, *g2;
g1 = new int[lim << 1], g2 = new int[lim];
Poly::division(Alpha, r - l + 1, gate[now << 1], mid - l + 1 + 1, g1, g2);
evaluation(now << 1, l, mid, g2, Beta, Zeta);
Poly::division(Alpha, r - l + 1, gate[now << 1 | 1], r - mid + 1, g1, g2);
evaluation(now << 1 | 1, mid + 1, r, g2, Beta, Zeta);
delete[] g1, delete[] g2;
}
int g1[maxn], g2[maxn];
void Evaluation(int *Alpha, int len, int *Beta, int n, int *Zeta) {
init(1, 1, n, Beta);
Poly::division(Alpha, len, gate[1], n + 1, g1, g2);
return evaluation(1, 1, n, g2, Beta, Zeta);
}
int f1[maxn], f2[maxn], ell[maxn];
int *Steins[maxn << 1], e1[maxn], e2[maxn], G1[maxn], G2[maxn];
void interpolation(int now, int l, int r) {
if (l == r) {
Steins[now] = new int[1];
return void(Steins[now][0] = ell[l]);
}
Steins[now] = new int[r - l + 1];
int mid = (l + r) >> 1, lim = 1;
interpolation(now << 1, l, mid), interpolation(now << 1 | 1, mid + 1, r);
while (lim < (r - l + 1)) lim <<= 1;
copy(G1, Steins[now << 1], mid - l + 1), copy(G2, Steins[now << 1 | 1], r - mid);
copy(e1, gate[now << 1 | 1], r - mid + 1), copy(e2, gate[now << 1], mid - l + 1 + 1);
Poly::convolution(e1, r - mid + 1, G1, mid - l + 1, e1);
Poly::convolution(e2, mid - l + 1 + 1, G2, r - mid, e2);
for (int i = 0; i <= r - l; i++) Steins[now][i] = (e1[i] + e2[i]) % mod;
}
void Interpolation(int *Alpha, int *Beta, int n, int *Zeta) {
//Alpha->x,Beta->y
init(1, 1, n, Alpha);
copy(f1, gate[1], n + 1);
Poly::derivative(f1, n + 1, f2);
evaluation(1, 1, n, f2, Alpha, ell);
for (int i = 1; i <= n; i++) ell[i] = 1ll * Beta[i] * fastpow(ell[i], mod - 2) % mod;
interpolation(1, 1, n);
return copy(Zeta, Steins[1], n);
}
}
int n;
int Alpha[maxn], Beta[maxn], Zeta[maxn];
typedef long long ll;
ll fr[maxn];
ll C(ll N1, ll M1){
return fr[M1] * fr[N1 - M1] % mod * fastpow(fr[N1], mod - 2) % mod;
}
void solve() {
scanf("%d", &n);
ll K = 1;
for (int i = 1; i <= n; i++) scanf("%d", &Alpha[i]), Beta[i] = 0, K *= Alpha[i], K %= mod;
Alpha[++ n] = 0, Beta[n] = K;
Multi_point::Interpolation(Alpha, Beta, n, Zeta);
ll ans = 0, inv = fastpow(Zeta[n - 1], mod - 2);
// std::cerr << Zeta[n - 1] << ' ';
for (int i = 0; i < n - 1; i++){
if(((i ^ n) & 1))ans += C(n - 1, i) * Zeta[i] % mod;
else ans -= C(n - 1, i) * Zeta[i] % mod;
ans %= mod;
// std::cerr << Zeta[i] << ' ';
}
// std::cerr << std::endl;
ans = (ans * inv) % mod;
io << (ans + mod) % mod << '\n';
}
int main() {
int T;
fr[0] = 1;
for(int i =1 ; i < 100000 + 10; ++ i){
fr[i] = fr[i - 1] * i % mod;
}
scanf("%d", &T);
while (T--) {
solve();
}
// scanf("%d",&n);for(int i=1;i<=n;i++) scanf("%d%d",&Alpha[i],&Beta[i]);
// Multi_point::Interpolation(Alpha,Beta,n,Zeta);
// for(int i=0;i<n;i++) io << Zeta[i] << " \n"[i==n-1];
// return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 0ms
memory: 28588kb
input:
3 3 1 2 3 1 10 4 5 5 5 5
output:
665496247 10 780
result:
ok 3 lines
Test #2:
score: 0
Accepted
time: 4ms
memory: 24824kb
input:
100 1 847297038 5 203751343 825662680 957256277 500052871 818834331 5 987146111 742744954 629579339 780044373 494679147 8 251614896 194569580 916578218 533049529 530535094 733501237 367273760 385341463 7 375252389 260364079 389447501 409464874 846572964 772775526 503458256 2 123436633 211941084 6 19...
output:
847297038 51970068 170556219 113431915 760262074 246542542 195147099 493093785 168144980 126946554 710105918 669760399 717542211 546162274 355117267 476319791 504479282 611041492 409057254 586259120 411524107 467323677 604713606 677086599 337208713 428207507 929439958 108098278 655034669 220455699 6...
result:
ok 100 lines
Test #3:
score: 0
Accepted
time: 15ms
memory: 24224kb
input:
100 34 426400575 9927300 909720899 954255675 767998905 83905549 11564853 733479914 519688252 588206942 292994501 808946771 354495122 756030286 580925234 595222682 950714227 281486657 916585766 73918645 344801620 269358971 823314063 624176199 663573632 222827631 43334235 771899654 651401397 286161985...
output:
407047195 969184260 707290913 588793971 161624956 900764379 946042111 525481567 323619066 559679400 702641543 774077417 72041789 230297993 843180691 511827230 391868728 132163026 337301045 628148033 958328653 291354147 301471681 130398071 507222983 737846714 753300919 174373074 657380065 424492703 8...
result:
ok 100 lines
Test #4:
score: -100
Wrong Answer
time: 249ms
memory: 44504kb
input:
100 718 404314538 399059943 992580922 926005407 338582419 649174215 974473772 173983508 842966562 421761508 29390122 51320322 611981261 892915925 76490050 235705837 849990374 33308970 67066467 977102595 675867852 125129873 255787127 312018985 952054434 722094045 171206475 890973351 126578304 3894293...
output:
995895670 994710069 713279557 626113157 685298699 907804742 382977068 204900737 784029914 680667123 403672352 99600221 456001194 444900792 239883144 340277780 204991006 861302818 509148571 413682190 7764599 301884750 936011407 341104983 603994110 403819556 641759875 377501122 207128991 70300471 3752...
result:
wrong answer 25th lines differ - expected: '78171640', found: '603994110'