Mlxa

TEAMBOOK FFT по модулю

Nov 1st, 2019
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.04 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2. using double_type   = double;
  3. using long_type     = long long;
  4. #define double  double_type
  5. #define long    long_type
  6. #define all(x) x.begin(), x.end()
  7. using namespace std;
  8.  
  9. const int mod = 786433;
  10. const int g   = 10;
  11.  
  12. struct num {
  13.     int a;
  14.     num(int x) :
  15.         a(x)  {}
  16.     num() :
  17.         a(0) {}
  18. };
  19. num operator+(const num &a, const num &b) {
  20.     return (a.a + b.a) % mod;
  21. }
  22. num operator-(const num &a, const num &b) {
  23.     return (a.a + mod - b.a) % mod;
  24. }
  25. num operator*(const num &a, const num &b) {
  26.     return ((long)a.a * b.a) % mod;
  27. }
  28. num powermod(num a, int p) {
  29.     num x = 1;
  30.     for (; p > 0; p >>= 1) {
  31.         if (p & 1) {
  32.             x = x * a;
  33.         }
  34.         a = a * a;
  35.     }
  36.     return x;
  37. }
  38. void operator/=(num &a, int k) {
  39.     a = a * powermod(k, mod - 2);
  40. }
  41. istream &operator>>(istream &in, num &x) {
  42.     return in >> x.a;
  43. }
  44. ostream &operator<<(ostream &out, const num x) {
  45.     return out << x.a;
  46. }
  47.  
  48. #ifdef LC
  49. const int max_log   = 16;
  50. #else
  51. const int max_log   = 16;
  52. #endif
  53. const int max_len   = 1 << max_log;
  54.  
  55. int rev[max_len];
  56.  
  57. void fft_init(int k) {
  58.     int n = 1 << k;
  59.     for (int i = 1; i < n; ++i) {
  60.         rev[i] = rev[i >> 1] >> 1;
  61.         rev[i] |= (i & 1) << (k - 1);
  62.     }
  63. }
  64.  
  65. void fft_dir(num *a, int k) {
  66.     int n = (1 << k);
  67.     for (int i = 0; i < n; ++i) {
  68.         if (i < rev[i]) {
  69.             swap(a[i], a[rev[i]]);
  70.         }
  71.     }
  72.     for (int h = 1; h < n; h *= 2) {
  73.         assert((mod - 1) % (2 * h) == 0);
  74.         num mul = powermod(g, (mod - 1) / (2 * h));
  75.         for (int st = 0; st < n; st += 2 * h) {
  76.             num w = 1;
  77.             for (int i = st; i < st + h; ++i) {
  78.                 num x = a[i], y = a[i + h];
  79.                 a[i]        = x + w * y;
  80.                 a[i + h]    = x - w * y;
  81.                 w = w * mul;
  82.             }
  83.         }
  84.     }
  85. }
  86.  
  87. void fft_inv(num *a, int k) {
  88.     int n = (1 << k);
  89.     fft_dir(a, k);
  90.     for (int i = 0; i < n; ++i) {
  91.         a[i] /= n;
  92.     }
  93.     reverse(a + 1, a + n);
  94. }
  95.  
  96. num save_a[max_len], save_b[max_len], buff[max_len];
  97.  
  98. void fft_mul(num *a, num *b, num *res) {
  99.     fill(a + max_len / 2, a + max_len, 0);
  100.     fill(b + max_len / 2, b + max_len, 0);
  101.     copy(a, a + max_len, save_a);
  102.     copy(b, b + max_len, save_b);
  103.     fft_init(max_log);
  104.     fft_dir(save_a, max_log);
  105.     fft_dir(save_b, max_log);
  106.     for (int i = 0; i < max_len; ++i) {
  107.         buff[i] = save_a[i] * save_b[i];
  108.     }
  109.     fft_inv(buff, max_log);
  110.     for (int i = 1; i < max_len; ++i) {
  111.         res[i] = res[i] + buff[i - 1];
  112.     }
  113. }
  114.  
  115. const int max_h = 17;
  116.  
  117. num dp[max_h][max_len];
  118.  
  119. int main() {
  120. #ifdef LC
  121.     assert(freopen("input.txt", "r", stdin));
  122. #else
  123.     assert(freopen("avl.in", "r", stdin));
  124.     assert(freopen("avl.out", "w", stdout));
  125. #endif
  126.     ios::sync_with_stdio(0);
  127.     cin.tie(0);
  128.     dp[0][0] = 1;
  129.     dp[1][1] = 1;
  130.     for (int h = 2; h < max_h; ++h) {
  131.         auto check = [&](int lh, int rh) {
  132.             if (lh < 0 || rh < 0) {
  133.                 return;
  134.             }
  135.             fft_mul(dp[lh], dp[rh], dp[h]);
  136.             //~ for (int i = 0; i < 100; ++i) {
  137.                 //~ for (int j = 0; j < 100; ++j) {
  138.                     //~ dp[h][i + j + 1] = dp[h][i + j + 1] + dp[lh][i] * dp[rh][j];
  139.                 //~ }
  140.             //~ }
  141.         };
  142.         check(h - 2, h - 1);
  143.         check(h - 1, h - 2);
  144.         check(h - 1, h - 1);
  145.     }
  146.     int n, h;
  147.     cin >> n >> h;
  148.     cout << dp[h + 1][n].a << "\n";
  149.     return 0;
  150. }
Add Comment
Please, Sign In to add comment