Skip to content

Commit 92095f1

Browse files
committed
Updated polynomial.cpp to import from headers
1 parent 3ca9b81 commit 92095f1

File tree

1 file changed

+16
-232
lines changed

1 file changed

+16
-232
lines changed

fuzz-tests/numerical/Polynomial.cpp

Lines changed: 16 additions & 232 deletions
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,20 @@ poly interp(const vector<num> &x, const vector<num> &y) {
384384
} // namespace MIT
385385

386386
namespace mine {
387-
const ll mod = 998244353, root = 62;
387+
namespace ignore1 {
388+
#include "../../content/number-theory/ModPow.h"
389+
}
390+
namespace ignore2 {
391+
#include "../../content/number-theory/ModularArithmetic.h"
392+
}
393+
ll modpow(ll a, ll e);
394+
#include "../../content/numerical/NumberTheoreticTransform.h"
395+
ll modpow(ll a, ll e) {
396+
if (e == 0) return 1;
397+
ll x = modpow(a * a % mod, e >> 1);
398+
return e & 1 ? x * a % mod : x;
399+
}
400+
#include "../../content/numerical/FastFourierTransformMod.h"
388401
struct Mod {
389402
ll x;
390403
Mod() : x(0) {}
@@ -405,238 +418,9 @@ struct Mod {
405418
typedef Mod num;
406419
typedef vector<num> poly;
407420

408-
typedef complex<double> C;
409-
typedef complex<long double> Cd;
410-
typedef vector<double> vd;
411-
void fft(vector<C> &a, int n, int L, vector<C> &rt) {
412-
vi rev(n);
413-
rep(i, 0, n) rev[i] = (rev[i / 2] | (i & 1) << L) / 2;
414-
if (rt.empty()) {
415-
rt.assign(n, 1);
416-
for (int k = 2; k < n; k *= 2) {
417-
Cd z[] = {1, polar(1.0, M_PI / k)};
418-
rep(i, k, 2 * k) rt[i] = Cd(rt[i / 2]) * z[i & 1];
419-
}
420-
}
421-
rep(i, 0, n) if (i < rev[i]) swap(a[i], a[rev[i]]);
422-
for (int k = 1; k < n; k *= 2)
423-
for (int i = 0; i < n; i += 2 * k)
424-
rep(j, 0, k) {
425-
// C z = rt[j+k] * a[i+j+k]; // (25% faster if hand-rolled) /// include-line
426-
auto x = (double *)&rt[j + k], y = (double *)&a[i + j + k]; /// exclude-line
427-
C z(x[0] * y[0] - x[1] * y[1], x[0] * y[1] + x[1] * y[0]); /// exclude-line
428-
a[i + j + k] = a[i + j] - z;
429-
a[i + j] += z;
430-
}
431-
}
432-
vd conv(const vd &a, const vd &b) {
433-
if (a.empty() || b.empty())
434-
return {};
435-
vd res(sz(a) + sz(b) - 1);
436-
int L = 32 - __builtin_clz(sz(res)), n = 1 << L;
437-
vector<C> in(n), out(n), rt;
438-
copy(all(a), begin(in));
439-
rep(i, 0, sz(b)) in[i].imag(b[i]);
440-
fft(in, n, L, rt);
441-
trav(x, in) x *= x;
442-
rep(i, 0, n) out[i] = in[-i & (n - 1)] - conj(in[i]);
443-
fft(out, n, L, rt);
444-
rep(i, 0, sz(res)) res[i] = imag(out[i]) / (4 * n);
445-
return res;
446-
}
447-
448-
typedef vector<ll> vl;
449-
void ntt(vl &a, vl &rt, vl &rev, int n) {
450-
rep(i, 0, n) if (i < rev[i]) swap(a[i], a[rev[i]]);
451-
for (int k = 1; k < n; k *= 2)
452-
for (int i = 0; i < n; i += 2 * k)
453-
rep(j, 0, k) {
454-
ll z = rt[j + k] * a[i + j + k] % mod, &ai = a[i + j];
455-
a[i + j + k] = (z > ai ? ai - z + mod : ai - z);
456-
ai += (ai + z >= mod ? z - mod : z);
457-
}
458-
}
459-
460-
ll modpow(ll a, ll e) {
461-
if (e == 0)
462-
return 1;
463-
ll x = modpow(a * a % mod, e >> 1);
464-
return e & 1 ? x * a % mod : x;
465-
}
466-
467-
vl conv(const vl &a, const vl &b) {
468-
if (a.empty() || b.empty())
469-
return {};
470-
int s = sz(a) + sz(b) - 1, B = 32 - __builtin_clz(s), n = 1 << B;
471-
vl L(a), R(b), out(n), rt(n, 1), rev(n);
472-
L.resize(n), R.resize(n);
473-
rep(i, 0, n) rev[i] = (rev[i / 2] | (i & 1) << B) / 2;
474-
ll curL = mod / 2, inv = modpow(n, mod - 2);
475-
for (int k = 2; k < n; k *= 2) {
476-
ll z[] = {1, modpow(root, curL /= 2)};
477-
rep(i, k, 2 * k) rt[i] = rt[i / 2] * z[i & 1] % mod;
478-
}
479-
ntt(L, rt, rev, n);
480-
ntt(R, rt, rev, n);
481-
rep(i, 0, n) out[-i & (n - 1)] = L[i] * R[i] % mod * inv % mod;
482-
ntt(out, rt, rev, n);
483-
return {out.begin(), out.begin() + s};
484-
}
485-
486-
template <int M> vl convMod(const vl &a, const vl &b) {
487-
if (a.empty() || b.empty()) return {};
488-
vl res(sz(a) + sz(b) - 1);
489-
int B=32-__builtin_clz(sz(res)), n = 1<<B, cut=int(sqrt(M));
490-
vector<C> L(n), R(n), outs(n), outl(n), rt;
491-
rep(i,0,sz(a)) L[i] = Cd(a[i] / cut, a[i] % cut);
492-
rep(i,0,sz(b)) R[i] = Cd(b[i] / cut, b[i] % cut);
493-
fft(L, n, B, rt), fft(R, n, B, rt);
494-
rep(i,0,n) {
495-
int j = -i & (n - 1);
496-
outl[j] = (L[i] + conj(L[j])) * R[i] / (2.0 * n);
497-
outs[j] = (L[i] - conj(L[j])) * R[i] / (2.0 * n) / 1i;
498-
}
499-
fft(outl, n, B, rt), fft(outs, n, B, rt);
500-
rep(i,0,sz(res)) {
501-
ll av = ll(outl[i].real()+.5), cv = ll(outs[i].imag()+.5);
502-
ll bv = ll(outl[i].imag()+.5) + ll(outs[i].real()+.5);
503-
res[i] = ((av % M * cut + bv % M) * cut + cv % M) % M;
504-
}
505-
return res;
506-
}
507-
vector<Mod> conv(vector<Mod> a, vector<Mod> b) {
508-
// auto res = convMod<mod>(vl(all(a)), vl(all(b)));
509-
auto res = conv(vl(all(a)), vl(all(b)));
510-
return vector<Mod>(all(res));
511-
}
512-
poly &operator+=(poly &a, const poly &b) {
513-
a.resize(max(sz(a), sz(b)));
514-
rep(i, 0, sz(b)) a[i] = a[i] + b[i];
515-
return a;
516-
}
517-
poly &operator-=(poly &a, const poly &b) {
518-
a.resize(max(sz(a), sz(b)));
519-
rep(i, 0, sz(b)) a[i] = a[i] - b[i];
520-
return a;
521-
}
522-
523-
poly &operator*=(poly &a, const poly &b) {
524-
if (sz(a) + sz(b) < 100){
525-
poly res(sz(a) + sz(b) - 1);
526-
rep(i,0,sz(a)) rep(j,0,sz(b))
527-
res[i + j] = (res[i + j] + a[i] * b[j]);
528-
return (a = res);
529-
}
530-
return a = conv(a, b);
531-
}
532-
poly operator*(poly a, const num b) {
533-
poly c = a;
534-
trav(i, c) i = i * b;
535-
return c;
536-
}
537-
#define OP(o, oe) \
538-
poly operator o(poly a, poly b) { \
539-
poly c = a; \
540-
return c oe b; \
541-
}
542-
OP(*, *=) OP(+, +=) OP(-, -=);
543-
poly modK(poly a, int k) { return {a.begin(), a.begin() + min(k, sz(a))}; }
544-
poly inverse(poly A) {
545-
poly B = poly({num(1) / A[0]});
546-
while (sz(B) < sz(A))
547-
B = modK(B * (poly({num(2)}) - modK(A, 2*sz(B)) * B), 2 * sz(B));
548-
return modK(B, sz(A));
549-
}
550-
poly &operator/=(poly &a, poly b) {
551-
if (sz(a) < sz(b))
552-
return a = {};
553-
int s = sz(a) - sz(b) + 1;
554-
reverse(all(a)), reverse(all(b));
555-
a.resize(s), b.resize(s);
556-
a = a * inverse(b);
557-
a.resize(s), reverse(all(a));
558-
return a;
559-
}
560-
OP(/, /=)
561-
poly &operator%=(poly &a, poly &b) {
562-
if (sz(a) < sz(b))
563-
return a;
564-
poly c = (a / b) * b;
565-
a.resize(sz(b) - 1);
566-
rep(i, 0, sz(a)) a[i] = a[i] - c[i];
567-
return a;
568-
}
569-
OP(%, %=)
570-
poly deriv(poly a) {
571-
if (a.empty())
572-
return {};
573-
poly b(sz(a) - 1);
574-
rep(i, 1, sz(a)) b[i - 1] = a[i] * num(i);
575-
return b;
576-
}
577-
poly integr(poly a) {
578-
if (a.empty()) return {0};
579-
poly b(sz(a) + 1);
580-
b[1] = num(1);
581-
rep(i, 2, sz(b)) b[i] = b[mod%i]*Mod(-mod/i+mod);
582-
rep(i, 1 ,sz(b)) b[i] = a[i-1] * b[i];
583-
return b;
584-
}
585-
poly log(poly a) { return modK(integr(deriv(a) * inverse(a)), sz(a)); }
586-
poly exp(poly a) {
587-
poly b(1, num(1));
588-
if (a.empty())
589-
return b;
590-
while (sz(b) < sz(a)) {
591-
b.resize(sz(b) * 2);
592-
b *= (poly({num(1)}) + modK(a, sz(b)) - log(b));
593-
b.resize(sz(b) / 2 + 1);
594-
}
595-
return modK(b, sz(a));
596-
}
597-
poly pow(poly a, ll m) {
598-
int p = 0, n = sz(a);
599-
while (p < sz(a) && a[p].x == 0)
600-
++p;
601-
if (ll(m)*p >= sz(a)) return poly(sz(a));
602-
num j = a[p];
603-
a = {a.begin() + p, a.end()};
604-
a = a * (num(1) / j);
605-
a.resize(n);
606-
auto res = exp(log(a) * num(m)) * (j ^ m);
607-
res.insert(res.begin(), p*m, 0);
608-
return modK(res, n);
609-
}
610-
611-
vector<num> eval(const poly &a, const vector<num> &x) {
612-
int n = sz(x);
613-
if (!n) return {};
614-
vector<poly> up(2 * n);
615-
rep(i, 0, n) up[i + n] = poly({num(0) - x[i], 1});
616-
for (int i = n - 1; i > 0; i--)
617-
up[i] = up[2 * i] * up[2 * i + 1];
618-
vector<poly> down(2 * n, poly(1,0));
619-
down[1] = a % up[1];
620-
rep(i, 2, 2 * n)
621-
down[i] = down[i / 2] % up[i];
622-
vector<num> y(n);
623-
rep(i, 0, n) y[i] = down[i + n][0];
624-
return y;
625-
}
626-
627-
poly interp(vector<num> x, vector<num> y) {
628-
int n=sz(x);
629-
vector<poly> up(n*2);
630-
rep(i,0,n) up[i+n] = poly({num(0)-x[i], num(1)});
631-
for(int i=n-1; i>0;i--) up[i] = up[2*i]*up[2*i+1];
632-
vector<num> a = eval(deriv(up[1]), x);
633-
vector<poly> down(2*n);
634-
rep(i,0,n) down[i+n] = poly({y[i]*(num(1)/a[i])});
635-
for(int i=n-1;i>0;i--) down[i] = down[i*2] * up[i*2+1] + down[i*2+1] * up[i*2];
636-
return down[1];
637-
}
638-
421+
#include "../../content/numerical/FFTPolynomial.h"
639422
} // namespace mine
423+
640424
pair<mine::poly, MIT::poly> genVec(int sz) {
641425
mine::poly a;
642426
MIT::poly am;

0 commit comments

Comments
 (0)