QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#125885 | #622. 多项式多点求值 | NOI_AK_ME# | 0 | 29ms | 13784kb | C++23 | 10.0kb | 2023-07-17 20:53:26 | 2023-07-17 20:53:28 |
Judging History
answer
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
namespace ModularPolynomial
{
#define CE constexpr
#define SC(a,b) static_cast<a>(b)
using u = unsigned; using ull = unsigned long long;
CE const u mod = 998244353, G = 3, modM1 = mod - 1, modM2 = mod - 2, modM1D2 = modM1 / 2, modM1D4 = modM1 / 4, mod2M2 = modM1 * 2; CE const ull modmod2 = SC(ull, mod) * mod * 2;
inline CE u Power(u a, u b) { u ans = 1; for (; b; a = SC(ull, a) * a % mod, b /= 2) if (b % 2) ans = ans * SC(ull, a) % mod; return ans; }
inline CE u Inv(const u val) { return Power(val, modM2); } inline CE u Div2(const u val) { return (val % 2 ? val + mod : val) / 2; }
inline CE void UpdateInc(u& pos, const u val) { if ((pos += val) >= mod) pos -= mod; return; } inline CE u UnderflowReduce(const u val) { return SC(int, val) < 0 ? (val + mod) : val; }
inline CE void UpdateDec(u& pos, const u val) { if (SC(int, pos -= val) < 0) pos += mod; return; } inline CE u CeilLog2(const u val) { return val > 1 ? 32 - __builtin_clz(val - 1) : 1; }
struct ArrayPointer { void* p; template<class T1, class T2> ArrayPointer(std::vector<T1, T2>& v) :p(v.data()) {} template<class T> ArrayPointer(T* const _) : p(_) {} };
struct ConstArrayPointer
{
const void* p; template<class T1, class T2> inline ConstArrayPointer(const std::vector<T1, T2>& v) :p(v.data()) {} template<class T> inline ConstArrayPointer(const T* const _) : p(_) {}
};
inline void MemoryCopy(const ArrayPointer dest, const ConstArrayPointer source, const size_t size) { memcpy(dest.p, source.p, size); return; }
inline void MemoryClear(ArrayPointer dest, const size_t size) { memset(dest.p, 0, size); return; }
CE const u inv_G = Inv(G), sqrt_M1 = Power(G, modM1D4), inv_sqrtM1 = mod - sqrt_M1; CE const size_t sizeof_u = sizeof(u); std::vector<u> ur;
class Poly :public std::vector<u>
{
using base = std::vector<u>;
public:
using base::base; inline Poly(const u siz) :base(siz) {} inline void reserve(const u new_size) { base::reserve(new_size); return; } inline u size()const { return SC(u, base::size()); }
inline void resize(const u new_size) { base::resize(new_size); return; } inline void resize(const u new_size, const u init) { base::resize(new_size, init); return; }
inline void expand(const u new_size) { if (new_size > size()) resize(new_size); return; } inline u operator[](const u pos)const { return base::operator[](pos); }
inline u& operator[](const u pos) { return base::operator[](pos); } inline u* operator+(const u d) { return data() + d; } inline const u* operator+(const u d)const { return data() + d; }
};
inline void Prepare(const u maxi_length)
{
if (maxi_length == 1) { ur.resize(2, 1); return; } const u l = CeilLog2(maxi_length), siz_ur = 1u << l, w = Power(G, modM1 >> l); ur.resize(siz_ur); ur[siz_ur / 2] = 1;
for (u i = siz_ur / 2 + 1; i != siz_ur; ur[i] = ur[i - 1] * SC(ull, w) % mod, ++i); for (u i = siz_ur / 2 - 1; i; ur[i] = ur[SC(size_t, i * 2)], --i); return;
}
inline void DIFNTT(const u length, u* const a)
{
for (u i = length, * const end_p = a + length; i != 1;) for (u i2 = i, *p = (i /= 2, a); p != end_p; p += i)
for (u j = i, t; j != i2; t = *p, UpdateInc(*p, *(p + i)), *(p + i) = SC(ull, t + mod - *(p + i)) * ur[j++] % mod, ++p);
return;
}
inline void DITNTT(const u length, u* const a)
{
for (u i = 1, i2 = 2, * const end_p = a + length; i != length; i = i2, i2 *= 2) for (u* p = a; p != end_p; p += i)
for (u j = i, t; j != i2; *(p + i) = UnderflowReduce(*p - (t = SC(ull, *(p + i)) * ur[j++] % mod)), UpdateInc(*(p++), t)); return;
}
inline void DIFNTT(const u length, Poly& a) { DIFNTT(length, a.data()); return; } inline void DITNTT(const u length, Poly& a) { DITNTT(length, a.data()); return; }
inline void Mul(const u ans_length, Poly& a, Poly& b)
{
const u log_l = CeilLog2(a.size() + b.size() - 1), l = 1u << log_l, inv_l = mod - (modM1 >> log_l); a.resize(l); b.resize(l); DIFNTT(l, a); DIFNTT(l, b);
for (u i = 0; i < l; b[i] = SC(ull, a[i]) * b[i] % mod, ++i); DITNTT(l, b); a.front() = b.front() * SC(ull, inv_l) % mod;
for (u i = 1, end_i = std::min(ans_length, l); i < end_i; a[i] = b[l - i] * SC(ull, inv_l) % mod, ++i); a.resize(ans_length); return;
}
inline void Inv(const u ans_length, Poly& a, Poly& ans)
{
static Poly aux1, aux2; const u l = 1u << CeilLog2(ans_length), limit = a.size(); a.expand(l); ans.resize(l); aux1.resize(l); aux2.resize(l); ans.front() = Inv(a.front());
for (u i = 1, p_gn = 0; i < ans_length; ++p_gn)
{
const u i2 = i * 2, inv_i2 = mod - (modM1D2 >> p_gn), inv_i = mod - (modM1 >> p_gn);
if (i2 > limit) { MemoryCopy(aux1, a, limit * sizeof_u); MemoryClear(aux1 + limit, SC(size_t, i2 - limit) * sizeof_u); }
else MemoryCopy(aux1, a, i2 * sizeof_u); DIFNTT(i2, aux1); MemoryCopy(aux2, ans, i * sizeof_u); MemoryClear(aux2 + i, i * sizeof_u);
DIFNTT(i2, aux2); for (u j = 0; j < i2; aux2[j] = (aux1[j] * SC(ull, aux2[j]) + modM1) % mod * aux2[j] % mod, ++j); DITNTT(i2, aux2);
aux1[0] = aux2[0] * SC(ull, inv_i2) % mod; for (u j = 1; j < i2; aux1[j] = aux2[i2 - j] * SC(ull, inv_i2) % mod, ++j);
for (u j = 0, p = i2; j < i; aux2[j] = (a[j] + a[i | j] * SC(ull, sqrt_M1)) % mod * ur[p] % mod, ans[i | j] = ans[j] * SC(ull, ur[p++]) % mod, ++j);
DIFNTT(i, aux2); DIFNTT(i, ans + i); for (u j = 0; j < i; aux2[j] = (aux2[j] * SC(ull, ans[i | j]) + modM1) % mod * ans[i | j] % mod, ++j);
DITNTT(i, aux2); ans[i] = Div2((modmod2 - (SC(ull, aux2.front()) * inv_i + aux1.front()) % mod * inv_sqrtM1 - aux1[i]) % mod); const u end_j = std::min(i, ans_length - i);
for (u j = 1, p1 = i2, p2 = i2 * 2; j < end_j; ++j)
ans[i | j] = Div2(((aux2[i - j] * SC(ull, inv_i) + SC(ull, aux1[j]) * ur[++p1]) % mod * inv_sqrtM1 % mod * ur[--p2] + mod - aux1[i | j]) % mod); i = i2;
}
ans.resize(ans_length); return;
}
#undef SC
#undef CE
}
using ModularPolynomial::ur;
using ModularPolynomial::mod;
using ModularPolynomial::ull;
using ModularPolynomial::Poly;
using ModularPolynomial::modM1;
using ModularPolynomial::DIFNTT;
using ModularPolynomial::DITNTT;
using ModularPolynomial::CeilLog2;
using ModularPolynomial::UpdateInc;
using ModularPolynomial::MemoryClear;
using ModularPolynomial::UnderflowReduce;
#define SC(a, b) static_cast<a>(b)
constexpr const size_t sizeof_unsigned = sizeof(unsigned);
char buf[2097152], buf_t[8], * pout = buf;
const char* pin = buf;
inline unsigned ReadU() { for (; *pin < '0'; ++pin); unsigned ans = *pin ^ '0'; for (; *(++pin) >= '0'; ans = ans * 10 + *pin - '0'); return ans; }
inline void WriteUE(unsigned v) { char l = 0; for (; v > 9; buf_t[l++] = v % 10, v /= 10); for (*pout = v ^ '0'; l; *(++pout) = buf_t[--l] ^ '0'); *(pout + 1) = '\n'; pout += 2; return; }
unsigned m, a[64046];
Poly aux1, aux2, tr[128821];
constexpr Poly& tr_2 = tr[2];
inline void Build(const unsigned L, const unsigned R, const unsigned father_l)
{
if (L == R)
{
if (father_l)
{
const unsigned pos = L * 2;
tr[pos].resize(father_l);
tr[pos].front() = mod - a[L];
tr[pos][1] = 1;
DIFNTT(father_l, tr[pos]);
}
else
{
tr_2.resize(2);
tr_2.front() = mod - a[L];
tr_2.back() = 1;
}
}
else
{
const unsigned mid = (L + R) / 2, log_l = CeilLog2(R - L + 2), l = 1u << log_l;
Build(L, mid, l);
Build(mid + 1, R, l);
const Poly& lc = tr[(L + mid) | (L < mid)], & rc = tr[(mid + 1 + R) | (mid + 1 < R)];
Poly& tr_pos = tr[(L + R) | (L < R)];
if (father_l)
{
tr_pos.resize(father_l);
for (unsigned i = 0; i < l; tr_pos[i] = SC(ull, lc[i]) * rc[i] % mod, ++i);
if (l != father_l)
{
aux1.resize(l);
unsigned* const p = tr_pos + l;
MemoryCopy(aux1, tr_pos, l * sizeof_unsigned);
DITNTT(l, aux1);
const unsigned inv_l = mod - (modM1 >> log_l), * const v = ur.data() + l;
*p = SC(ull, aux1.front()) * inv_l % mod;
for (unsigned i = 1; i < l; p[i] = SC(ull, aux1[l - i]) * inv_l % mod * v[i] % mod, ++i);
DIFNTT(l, p);
}
}
else
{
aux1.resize(l);
for (unsigned i = 0; i < l; aux1[i] = SC(ull, lc[i]) * rc[i] % mod, ++i);
DITNTT(l, aux1);
tr_pos.resize(m + 1);
const unsigned inv_l = mod - (modM1 >> log_l);
tr_pos.front() = SC(ull, aux1.front()) * inv_l % mod;
for (unsigned i = 1; i <= m; tr_pos[i] = SC(ull, aux1[l - i]) * inv_l % mod, ++i);
}
}
return;
}
inline void Solve(const unsigned L, const unsigned R)
{
if (L == R)
{
a[L] = tr[L * 2].front();
}
else
{
const unsigned mid = (L + R) / 2, RMLP1 = R - L + 1, log_l = CeilLog2(RMLP1), l = 1u << log_l, inv_l = mod - (modM1 >> log_l), dl = R - mid, dr = mid - L + 1;
aux1.resize(l);
aux2.resize(l);
Poly& tr_pos = tr[(L + R) | (L < R)], & lc = tr[(L + mid) | (L < mid)], & rc = tr[(mid + 1 + R) | (mid + 1 < R)];
tr_pos.resize(l);
DIFNTT(l, tr_pos);
for (unsigned i = 0; i < l; aux1[i] = SC(ull, tr_pos[i]) * rc[i] % mod, aux2[i] = SC(ull, tr_pos[i]) * lc[i] % mod, ++i);
DITNTT(l, aux1);
DITNTT(l, aux2);
for (unsigned i = dl; i < RMLP1; lc[i - dl] = SC(ull, aux1[l - i]) * inv_l % mod, ++i);
MemoryClear(lc + dr, SC(size_t, l - dr) * sizeof_unsigned);
for (unsigned i = dr; i < RMLP1; rc[i - dr] = SC(ull, aux2[l - i]) * inv_l % mod, ++i);
MemoryClear(rc + dl, SC(size_t, l - dl) * sizeof_unsigned);
Solve(L, mid);
Solve(mid + 1, R);
}
return;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
cin.read(buf, 2097152);
const unsigned n = ReadU();
ModularPolynomial::Prepare(n + max(n + 2, m = ReadU()));
Poly f(n + 1);
for (unsigned i = 0; i <= n; f[i++] = ReadU());
for (unsigned i = 1; i <= m; a[i++] = ReadU());
Build(1, m, 0);
auto& tr_root = tr[(1 + m) | (1 < m)];
reverse(tr_root.begin(), tr_root.end());
Inv(n + 1, tr_root, aux1);
reverse(aux1.begin(), aux1.end());
Mul(n + m, f, aux1);
tr_root.resize(m);
MemoryCopy(tr_root, f + n, SC(size_t, m) * sizeof_unsigned);
Solve(1, m);
for (unsigned i = 1; i <= m; WriteUE(a[i++]));
cout.write(buf, pout - buf);
}
详细
Test #1:
score: 0
Wrong Answer
time: 0ms
memory: 7344kb
input:
100 94 575336069 33153864 90977269 80162592 25195235 334936051 108161572 14050526 356949084 797375084 805865808 286113858 995555121 938794582 458465004 379862532 563357556 293989886 273730531 13531923 113366106 126368162 405344025 443053020 475686818 734878619 338356543 661401660 834651229 527993675...
output:
331986311 105318067 708178109 524387940 528813699 381700240 516550472 955080249 865139376 590236909 341283086 483238392 352918574 21819538 729564004 761120928 723412809 938447119 566265363 373961754 932052759 233747539 657941586 807733155 298593575 897973851 645897541 471817534 369391405 202859942 8...
result:
wrong answer 1st numbers differ - expected: '940122667', found: '331986311'
Test #2:
score: 0
Wrong Answer
time: 10ms
memory: 8500kb
input:
5000 4999 410683245 925831211 726803342 144364185 955318244 291646122 334752751 893945905 484134283 203760731 533867267 813509277 491860093 413174124 584582617 594704162 976489328 978500071 196938934 628117769 169796671 858963950 562124570 582491326 647830593 238623335 20782490 674939336 656529076 2...
output:
300110130 714130046 620385895 515754110 256622875 246759716 472711091 298167282 344987970 737384236 620072228 625068729 854593573 793211009 163050842 142819675 489843320 406061238 248605550 225442893 977551439 405615959 847908815 17549448 354128785 30446701 621065964 563154961 225926620 430503082 15...
result:
wrong answer 1st numbers differ - expected: '683038054', found: '300110130'
Test #3:
score: 0
Wrong Answer
time: 29ms
memory: 13784kb
input:
30000 29995 536696866 881441742 356233606 594487396 991820796 695996817 7219464 149265950 843761437 329761701 260625152 80366362 598729314 133794090 12808683 67477659 320740422 878134577 879383179 940923483 660160621 18082378 886078389 524050341 35092018 137623841 988429688 258507355 138475726 75726...
output:
896290547 730858152 629034857 292046306 180790081 76638496 631478439 843453302 987690435 333284256 709700472 472350304 735385697 98630832 76507423 734105396 365521486 173145170 194078421 449261433 962762318 510684073 661392860 589075634 449667620 808704063 382241303 160200718 396510466 66782135 8604...
result:
wrong answer 1st numbers differ - expected: '319541931', found: '896290547'
Test #4:
score: 0
Runtime Error
input:
100000 99989 703908936 826436271 431732352 607460686 960390248 897906950 506352459 662618885 172508812 713410533 704313866 156459539 879660919 98030681 46358006 400134234 121190289 498201666 616888945 210891377 39623412 687350951 269444705 980768130 381802923 553892268 644461704 287608268 554761733 ...
output:
result:
Test #5:
score: 0
Runtime Error
input:
1000000 999998 326289172 459965021 432610030 381274775 890620650 133203219 755508578 820410129 100497878 978894337 34545975 484258543 341383383 556328539 705716773 985485996 201697555 806763870 456757110 445252781 501965590 655584951 516373423 475444481 554722275 106826011 433893131 385018453 687541...