QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#5451#622. 多项式多点求值Qingyu100 ✓6326ms576960kbC++179.6kb2020-12-27 16:30:182021-12-19 06:19:55

Judging History

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

  • [2023-08-10 23:21:45]
  • System Update: QOJ starts to keep a history of the judgings of all the submissions.
  • [2021-12-19 06:19:55]
  • 评测
  • 测评结果:100
  • 用时:6326ms
  • 内存:576960kb
  • [2020-12-27 16:30:18]
  • 提交

answer

#pragma GCC optimize(3)
#include <bits/stdc++.h>

typedef long long ll;
constexpr int mod = 998244353;
const int N = 6e6 + 50;
const int g = 3;

inline int lc(int o) { return o << 1; }
inline int rc(int o) { return o << 1 | 1; }

inline int inc(int x, int y) { x += y - mod; return x + (x >> 31 & mod); }
inline int dec(int x, int y) { x -= y; return x + (x >> 31 & mod); }  
inline int mul(int x, int y) { return 1ll * x * y % mod; }
struct Math
{
	int fact[N], factinv[N], inv_e[N];
	inline int fastpow(int x, ll p)
	{
		int res = 1; 
		while (p)
		{
			if (p & 1) res = mul(res, x);
			x = mul(x, x);
			p >>= 1;
		}
		return res;
	}
	inline int inv(int x)
	{
		if (x < N) return inv_e[x];
		return fastpow(x, mod - 2);
	}
	Math()
	{
		fact[0] = factinv[0] = inv_e[0] = 1;
		for (int i = 1; i < N; ++i) fact[i] = mul(i, fact[i - 1]);
		factinv[N - 1] = fastpow(fact[N - 1], mod - 2);
		for (int i = N - 2; i >= 1; --i) factinv[i] = mul(i + 1, factinv[i + 1]);
		for (int i = 1; i < N; ++i) inv_e[i] = mul(fact[i - 1], factinv[i]);
	}
} mt;
struct Poly
{
	std::vector<int> v;
	Poly() { }
	Poly(std::vector<int> v) : v(v) {}
	Poly(std::initializer_list<int> v) : v(v) {}

	inline int deg() const { return v.size() - 1; }
	inline void redeg(int k) { v.resize(k + 1); }
	inline Poly slice(int k) const
	{
		if (k < v.size())
			return std::vector<int>(v.begin(), v.begin() + k + 1);
		std::vector<int> a(v);
		a.resize(k + 1);
		return a;
	}
	inline Poly clone() const { return slice(deg()); }
	inline void reverse() { std::reverse(v.begin(), v.end()); }
	inline void shrink()
	{
		int c = deg();
		while (c >= 0 && v[c] == 0) --c;
		v.resize(c + 1);
	}

	inline int& operator[](int k)
	{
		if (v.size() <= k) v.resize(k + 1);
		return v[k];
	}
	inline int operator[](int k) const
	{
		return v.size() <= k ? 0 : v[k];
	}
	inline int* base() { return v.begin().base(); }
	inline const int* base() const { return v.begin().base(); }
	inline void print() const
	{
		for (auto x : v) printf("%d ", x);
		putchar('\n');
	}

	inline Poly inv() const;
	inline Poly derivative() const;
	inline Poly integration() const;
	inline Poly ln() const;
	inline Poly exp() const;
	inline Poly reverse() const;
	inline std::vector<int> evaluation(const std::vector<int> &vals) const;
	inline void interpolation(const std::vector<std::pair<int, int> > &points);

	Poly(std::vector<std::pair<int, int> > points) { interpolation(points); }
};
struct FFT
{
	int len, k;
	int omega[N], omegaInv[N], rev[N];
	inline void init(int n)
	{
		int last_len = len;
		len = 1, k = 0;
		while (len <= n) len <<= 1, ++k;
		if (last_len == len) return;
		for (int i = 0; i < len; ++i) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (k - 1));
		omega[0] = omegaInv[0] = 1;
		const int primitive = mt.fastpow(g, (mod - 1) / len);
		for (int i = 1; i < len; ++i) omega[i] = omegaInv[len - i] = mul(omega[i - 1], primitive);
	}
	inline void operator() (Poly &a, const int *w)
	{
		if (a.v.size() < len) a.v.resize(len);
		for (int i = 0; i < len; ++i) if (i < rev[i]) std::swap(a.v[i], a.v[rev[i]]);
		for (int h = 1; h < len; h <<= 1)
			for (int t = len / (h << 1), j = 0; j < len; j += (h << 1))
			{
				const int *wn = w;
				for (int i = j; i < j + h; ++i)
				{
					const int _1 = a.v[i], _2 = mul(a.v[i + h], *wn);
					a.v[i] = inc(_1, _2);
					a.v[i + h] = dec(_1, _2);
					wn += t;
				}
			}
		if (w == omegaInv)
		{
			const int factor = mod - (mod - 1) / len;
			for (int i = 0; i < len; ++i) a.v[i] = mul(a.v[i], factor);
		}
	}
	inline void operator() (Poly &a, int op)
	{
		if (op == 1) operator()(a, omega);
		if (op == -1) operator()(a, omegaInv);
	}
} ntt;



inline Poly operator+(const Poly &P, const Poly &Q)
{
	Poly R;
	int deg = std::max(P.deg(), Q.deg());
	for (int i = 0; i <= deg; ++i) R[i] = inc(P[i], Q[i]);
	return R;
}

inline Poly operator-(const Poly &P, const Poly &Q)
{
	Poly R;
	int deg = std::max(P.deg(), Q.deg());
	for (int i = 0; i <= deg; ++i) R[i] = dec(P[i], Q[i]);
	return R;
}

inline Poly operator*(const Poly &_P, const Poly &_Q)
{
	Poly P = _P.clone(), Q = _Q.clone();
	int deg = P.deg() + Q.deg();
	Poly R;
	if (P.deg() + Q.deg() <= 200)
	{
		for (int i = 0; i <= P.deg(); ++i)
			for (int j = 0; j <= Q.deg(); ++j)
				R[i + j] = inc(R[i + j], mul(P[i], Q[j]));
		return R.slice(deg);
	}
	else
	{

		ntt.init(P.deg() + Q.deg() );
		ntt(P, 1); ntt(Q, 1);
		for (int i = 0; i < ntt.len; ++i) R[i] = mul(P[i], Q[i]);
		ntt(R, -1);
		return R.slice(deg);
	}
}

inline Poly PolyInv(const Poly &A)
{
	Poly Ax, R;
	
	int n = A.deg();
	if (n == 0) return Poly({ mt.inv(A[0]) });
	R = PolyInv(A.slice(A.deg() >> 1));
	ntt.init(A.deg() << 1);
	Ax = A.clone();
	ntt(Ax, 1); ntt(R, 1);
	for (int i = 0; i < ntt.len; ++i) Ax[i] = dec(mul(Ax[i], R[i]), 1);
	for (int i = 0; i < ntt.len; ++i) R[i] = mul(R[i], dec(1, Ax[i]));
	ntt(R, -1);
	R.redeg(n);
	return R;
}

inline Poly Poly::inv() const
{
	return PolyInv(*this);
}

inline Poly Poly::derivative() const
{
	Poly R;
	for (int i = 0; i < deg(); ++i) R[i] = mul(i + 1, operator[](i + 1));
	return R;
}

inline Poly Poly::integration() const
{
	Poly R;
	for (int i = 1; i <= deg(); ++i) R[i] = mul(mt.inv(i), operator[](i - 1));
	return R;
}

inline Poly Poly::ln() const
{
	return (derivative() * inv()).integration().slice(deg());
}

inline Poly PolyExp(const Poly &A)
{
	Poly Ax, Ay, R;
	int n = A.deg();
	if (n == 0) return Poly({1});
	R = PolyExp(A.slice(n >> 1)).slice(n);
	Ax = R.ln();
	Ay = A.slice(n);
	ntt.init(2 * n);
	ntt(R, 1), ntt(Ax, 1), ntt(Ay, 1);
	for (int i = 0; i < ntt.len; ++i)
		R[i] = mul(R[i], dec(inc(1, Ay[i]), Ax[i]));
	ntt(R, -1);
	return R;
}

inline Poly Poly::exp() const
{
	return PolyExp(*this).slice(deg());
}

inline std::pair<Poly, Poly> PolyDiv(const Poly &F, const Poly &G)
{
	Poly Fx, Gx, GrInv, Px, P, Q;
	int n = F.deg(), m = G.deg(); 
	Fx = F.clone(), Gx = G.clone();
	Fx.reverse(); Gx.reverse(); Fx.redeg(n - m + 1);
	Gx.redeg(std::max(m, n - m)); GrInv = Gx.inv(); 
	P = Fx * GrInv;

	P.redeg(n - m); P.reverse(); Gx = G.clone();
	Q = Gx * P; Q.redeg(m - 1);
	for (int i = 0; i <= m - 1; ++i) Q[i] = dec(F[i], Q[i]);
	return std::make_pair(Q, P);
}

inline Poly operator%(const Poly &P, const Poly &Q) { return PolyDiv(P, Q).first; }
inline Poly operator/(const Poly &P, const Poly &Q) { return PolyDiv(P, Q).second; }

inline Poly Mul_T(const Poly &a, const Poly &b)
{
	Poly R, A = a.clone(), B = b.clone();
	if (A.deg() <= 200)
	{
		for (int i = a.deg(); i >= 0; --i)
			for (int j = std::max(0, i - (a.deg() - b.deg())); j <= std::min(i, b.deg()); ++j)
				R[i - j] = inc(R[i - j], mul(a[i], b[j]));
		return R;
	}
	else
	{
		B.reverse();
		ntt.init(A.deg());
		ntt(A, 1); ntt(B, 1);
		for (int i = 0; i < ntt.len; ++i) A[i] = mul(A[i], B[i]);
		ntt(A, -1);
		int c = 0;
		for (int i = b.deg(); i <= a.deg(); ++i) R[c++] = A[i];
		return R;
	}
}


inline std::vector<int> Poly::evaluation(const std::vector<int> &vals) const
{
	std::vector<Poly> T, F;
	int m = vals.size();
	int t = std::max(deg(), (int)vals.size() - 1);
	ntt.init(t);
	T.resize(t * 4); F.resize(t * 4);

	std::function<void(int, int, int)> solve = [&](int o, int l, int r)
	{
		T[0].redeg(-1);
		if (l == r) T[o] = Poly({1, dec(0, vals[l])});
		else
		{
			const int mid = l + r >> 1;
			solve(lc(o), l, mid); solve(rc(o), mid + 1, r);
			T[o] = T[lc(o)] * T[rc(o)];
		}
	};
	std::function<void(int, int, int, std::vector<int>&)> solve2 = [&](int o, int l, int r, std::vector<int> &ans)
	{
		if (l >= m) return;
		if (l == r) ans.push_back(F[o][0]);
		else
		{
			const int mid = l + r >> 1;
			F[lc(o)] = Mul_T(F[o], T[rc(o)]);
			F[rc(o)] = Mul_T(F[o], T[lc(o)]);
			solve2(lc(o), l, mid, ans); solve2(rc(o), mid + 1, r, ans);
		}
	};
	solve(1, 0, t);
	Poly Q = T[1].inv();
	Q.redeg(t); 
	Q.reverse();
	Poly R = Q * *this;
	for (int i = t; i <= R.deg(); ++i) F[1][i - t] = R[i];
	F[1].redeg(t);
	std::vector<int> ans;
	solve2(1, 0, t, ans);
	return ans;
}

inline void Poly::interpolation(const std::vector<std::pair<int, int> > &points)
{
	int n = points.size();
	std::vector<Poly> T(n << 2);
	std::vector<int> vals;
	for (auto v : points) vals.push_back(v.first);
	std::function<void(int, int, int)> solve = [&](int o, int l, int r)
	{
		if (l == r) T[o] = Poly({ dec(0, vals[l]), 1 });
		else
		{
			const int mid = l + r >> 1;
			solve(lc(o), l, mid); solve(rc(o), mid + 1, r);
			T[o] = T[lc(o)] * T[rc(o)];
		}
	};
	solve(1, 0, n - 1);
	Poly g = T[1], dg = g.derivative();
	std::vector<int> ys = dg.evaluation(vals);
	std::function<Poly(int, int, int)> solve2 = [&](int o, int l, int r)
	{
		if (l == r) return Poly({ mul(points[l].second, mt.inv(ys[l])) });
		const int mid = l + r >> 1;
		return solve2(lc(o), l, mid) * T[rc(o)] + solve2(rc(o), mid + 1, r) * T[lc(o)];
	};
	*this = solve2(1, 0, n - 1);
}

inline char nc()
{
	static char buf[1000000], *p1 = buf, *p2 = buf;
	return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2) ? EOF : *p1++;
}

inline int read()
{
	int res = 0;
	char ch;
	do ch = nc(); while (ch < 48 || ch > 57);
	do res = res * 10 + ch - 48, ch = nc(); while (ch >= 48 && ch <= 57);
	return res;
}

int main()
{
	int n = read() - 1, m = read(), t = std::max(n, m - 1);
	Poly P;
	for (int i = 0; i <= n; ++i) P[i] = read();
	std::vector<int> vals;
	for (int i = 0; i < m; ++i) vals.push_back(read());
	std::vector<int> result = P.evaluation(vals);
	for (auto v : result) printf("%d\n", v);
	return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 20
Accepted
time: 72ms
memory: 75996kb

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 144406394 378702795 37103065 620155262 386200819 687769223 720799109 633363778 220363528 486270209 495546404 568285636 546469553 547464490 456299149 851438618 974938642 505021716 551788648 962128802 ...

output:

940122667
397187437
905033404
346709388
146347009
49596361
125616024
966474950
693596552
162411542
248699477
217639076
254290825
963991654
951375739
431661136
587466850
933820245
135676159
683994808
821695954
675479292
463904298
15085475
183389374
976945620
668527277
98940366
909505808
904450031
968010385
173752422
653990367
303219309
6056931
554452378
488226286
332464785
610244217
516229529
125358101
533797869
439485040
161852365
733105817
105926146
106606714
630873105
857340320
87011036
678661...

result:

ok 94 numbers

Test #2:

score: 20
Accepted
time: 73ms
memory: 77492kb

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 238201224 657476464 10300038 590252533 468302687 287260562 719784076 907422891 533089046 672068066 229682183 373964848 244302770 117858543 11284821 961238173 246595260 517257997 870099722 351419275 538...

output:

683038054
713408290
776843174
52275065
602085453
905088100
991748340
720305324
831850056
296147844
79380797
882313010
941965313
987314872
363655479
380838721
51243733
165728533
592641557
679475455
651115426
60492203
787012426
247557193
136399242
484592897
908383514
735275879
648228244
443933835
550490997
625071079
774045911
554901737
448447574
512455509
498500488
216099918
604133346
174995590
498132830
268296096
49651043
561289208
330398949
69288559
8784168
82132295
185994726
946290818
953472996...

result:

ok 4999 numbers

Test #3:

score: 20
Accepted
time: 162ms
memory: 89968kb

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 757260406 127159828 417276756 586475417 26303169 572405083 944790202 566630572 474491009 320429623 194763885 174090432 732341110 942823560 276480235 170424410 95316057 838567371 692322276 655016111 4555558...

output:

319541931
71523627
374970852
25715597
36244629
300490421
920015579
97305810
949802809
507599156
733158280
569689405
234576135
266469534
141265915
989761030
221701009
895284489
707865101
547950933
844193939
688358883
642066256
113618699
877631874
804170817
455115375
47621629
66017800
747477619
281472115
923128701
301471998
505022080
461303133
560502815
595576539
848682480
835359115
166820633
579725395
119328881
237146267
291505646
983151226
839610961
696265452
115738219
353386994
620070023
765455...

result:

ok 29995 numbers

Test #4:

score: 20
Accepted
time: 614ms
memory: 124644kb

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 569616189 350624224 369805 882217037 672505285 227060683 101650396 365754412 844206684 573112907 157130192 338903039 879091569 870660644 698674844 513049853 480084099 371430418 943011467 44916984 8753...

output:

135579851
646286631
74078131
432534100
405499800
291350098
736555983
833523488
132230969
377599489
208993791
503865639
149603681
279216057
477463117
247401241
643979698
478954375
436185030
471378650
234144621
390722547
788177217
69823556
516048238
562200936
507083023
201497639
482025143
173466674
959752800
285281141
26703854
941765225
169981375
991697030
483548376
418821898
431112160
854644793
193452981
620608943
158637607
480389012
386906366
730401124
265607339
758806621
997953757
768924917
470...

result:

ok 99989 numbers

Test #5:

score: 20
Accepted
time: 6326ms
memory: 576960kb

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 687541322 148360017 545514961 595515236 437004728 787030520 480851576 368306115 160716250 515391381 14500734 159363046 564219952 598965450 866554878 545880928 547245599 863841250 661982619 980345860 8824065...

output:

606800783
817370938
237396973
847847757
644743839
247401674
83642110
430778992
481194348
734716471
284931123
740118779
149843259
354488296
948569346
267724213
148740992
487034502
874993826
268358083
945290837
793539526
571516423
380887985
556022428
430319434
939322
456132883
774969519
361006565
239058092
613185432
752196961
499650503
443579264
169840128
206218157
784814657
716427524
77823989
556319910
619497898
787301377
226345635
627609765
459532636
852381995
667636041
913081886
163159298
77598...

result:

ok 999998 numbers