@@ -384,7 +384,20 @@ poly interp(const vector<num> &x, const vector<num> &y) {
384
384
} // namespace MIT
385
385
386
386
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"
388
401
struct Mod {
389
402
ll x;
390
403
Mod () : x(0 ) {}
@@ -405,238 +418,9 @@ struct Mod {
405
418
typedef Mod num;
406
419
typedef vector<num> poly;
407
420
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"
639
422
} // namespace mine
423
+
640
424
pair<mine::poly, MIT::poly> genVec (int sz) {
641
425
mine::poly a;
642
426
MIT::poly am;
0 commit comments