Advertisement
noomaK

Untitled

Nov 1st, 2023
226
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.34 KB | None | 0 0
  1. #include "bits/stdc++.h"
  2. using namespace std;
  3.  
  4. typedef long long ll;
  5.  
  6. #define rep(i, a, b) for(int i = a; i < (b); ++i)
  7. #define all(x) begin(x), end(x)
  8. #define sz(x) (int)(x).size()
  9. typedef long long ll;
  10. typedef pair<int, int> pii;
  11. typedef vector<int> vi;
  12.  
  13. #define deb(...) logger(#__VA_ARGS__, __VA_ARGS__)
  14. template<typename ...Args>
  15. void logger(string vars, Args&&... values) {
  16.   cout << vars << " = ";
  17.   string delim = "";
  18.   (..., (cout << delim << values, delim = ", "));
  19.   cout << '\n';
  20. }
  21.  
  22. template<int MOD>
  23. struct ModInt {
  24.     long long v;
  25.     ModInt(long long _v = 0) {v = (-MOD < _v && _v < MOD) ? _v : _v % MOD; if (v < 0) v += MOD;}
  26.     ModInt& operator += (const ModInt &other) {v += other.v; if (v >= MOD) v -= MOD; return *this;}
  27.     ModInt& operator -= (const ModInt &other) {v -= other.v; if (v < 0) v += MOD; return *this;}
  28.     ModInt& operator *= (const ModInt &other) {v = v * other.v % MOD; return *this;}
  29.     ModInt& operator /= (const ModInt &other) {return *this *= inverse(other);}
  30.     bool operator == (const ModInt &other) const {return v == other.v;}
  31.     bool operator != (const ModInt &other) const {return v != other.v;}
  32.     friend ModInt operator + (ModInt a, const ModInt &b) {return a += b;}
  33.     friend ModInt operator - (ModInt a, const ModInt &b) {return a -= b;}
  34.     friend ModInt operator * (ModInt a, const ModInt &b) {return a *= b;}
  35.     friend ModInt operator / (ModInt a, const ModInt &b) {return a /= b;}
  36.     friend ModInt operator - (const ModInt &a) {return 0 - a;}
  37.     friend ModInt power(ModInt a, long long b) {ModInt ret(1); while (b > 0) {if (b & 1) ret *= a; a *= a; b >>= 1;} return ret;}
  38.     friend ModInt inverse(ModInt a) {return power(a, MOD - 2);}
  39.     friend istream& operator >> (istream &is, ModInt &m) {is >> m.v; m.v = (-MOD < m.v && m.v < MOD) ? m.v : m.v % MOD; if (m.v < 0) m.v += MOD; return is;}
  40.     friend ostream& operator << (ostream &os, const ModInt &m) {return os << m.v;}
  41. };
  42. using M = ModInt<998244353>;
  43.  
  44. template<typename T>
  45. vector<T> berlekampMassey(const vector<T> &s) {
  46.   vector<T> c;
  47.   vector<T> oldC;
  48.   int f = -1;
  49.   for (int i=0; i<(int)s.size(); i++) {
  50.     T delta = s[i];
  51.     for (int j=1; j<=(int)c.size(); j++)
  52.       delta -= c[j-1] * s[i-j];
  53.     if (delta == 0)
  54.       continue;
  55.     if (f == -1) {
  56.       c.resize(i + 1);
  57.       mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
  58.       for (T &x : c)
  59.         x = rng();
  60.       f = i;
  61.     } else {
  62.       vector<T> d = oldC;
  63.       for (T &x : d)
  64.         x = -x;
  65.       d.insert(d.begin(), 1);
  66.       T df1 = 0;
  67.       for (int j=1; j<=(int)d.size(); j++)
  68.         df1 += d[j-1] * s[f+1-j];
  69.       assert(df1 != 0);
  70.       T coef = delta / df1;
  71.       for (T &x : d)
  72.         x *= coef;
  73.       vector<T> zeros(i - f - 1);
  74.       zeros.insert(zeros.end(), d.begin(), d.end());
  75.       d = zeros;
  76.       vector<T> temp = c;
  77.       c.resize(max(c.size(), d.size()));
  78.       for (int j=0; j<(int)d.size(); j++)
  79.         c[j] += d[j];
  80.       if (i - (int) temp.size() > f - (int) oldC.size()) {
  81.         oldC = temp;
  82.         f = i;
  83.       }
  84.     }
  85.   }
  86.   return c;
  87. }
  88.  
  89. template<typename T>
  90. T solve(const vector<T> &c, const vector<T> &s, long long k) {
  91.     int n = (int) c.size();
  92.     assert(c.size() <= s.size());
  93.  
  94.     auto mul = [&] (const vector<T> &a, const vector<T> &b) -> vector<T> {
  95.       vector<T> ret(a.size() + b.size() - 1);
  96.       for (int i=0; i<(int)a.size(); i++)
  97.         for (int j=0; j<(int)b.size(); j++)
  98.           ret[i+j] += a[i] * b[j];
  99.       for (int i=(int)ret.size()-1; i>=n; i--)
  100.         for (int j=n-1; j>=0; j--)
  101.           ret[i-j-1] += ret[i] * c[j];
  102.       ret.resize(min((int) ret.size(), n));
  103.       return ret;
  104.     };
  105.  
  106.     vector<T> a = n == 1 ? vector<T>{c[0]} : vector<T>{0, 1}, x{1};
  107.     for (; k>0; k/=2) {
  108.       if (k % 2)
  109.         x = mul(x, a);
  110.       a = mul(a, a);
  111.     }
  112.     x.resize(n);
  113.  
  114.     T ret = 0;
  115.     for (int i=0; i<n; i++)
  116.       ret += x[i] * s[i];
  117.     return ret;
  118. }
  119.  
  120.  
  121. const int N = 1e5;
  122. const int K = 26;
  123. int trie[N + 2][K];
  124. int tc;
  125. int cnt[N + 2];
  126.  
  127. void insert(const string &s) {
  128.   int n = s.size();
  129.   int root = 0;
  130.   for (int i = 0; i < n; ++i) {
  131.     int c = s[i] - 'a';
  132.     if (!trie[root][c]) {
  133.       trie[root][c] = ++tc;
  134.     }
  135.     root = trie[root][c];
  136.   }
  137.   cnt[root] = 1;
  138. }
  139.  
  140. int suf[N];
  141.  
  142. void build() {
  143.   queue<int> q;
  144.   q.push(0);
  145.   while (!q.empty()) {
  146.     int u = q.front();
  147.     cnt[u] += cnt[suf[u]];
  148.     q.pop();
  149.     for (int i = 0; i < K; ++i) {
  150.       if (trie[u][i]) {
  151.         suf[trie[u][i]] = (u > 0) * trie[suf[u]][i];
  152.         q.push(trie[u][i]);
  153.       } else {
  154.         trie[u][i] = trie[suf[u]][i];
  155.       }
  156.     }
  157.   }
  158. }
  159.  
  160.  
  161. void solve() {
  162.   ll n, m;
  163.   cin >> n >> m;
  164.   vector<string> a(m);
  165.   for (auto &x : a) {
  166.     cin >> x;
  167.     insert(x);
  168.   }
  169.   vector<M> pw(2021);
  170.   pw[0] = 1;
  171.   for (int i = 1; i < 2021; ++i) pw[i] = pw[i - 1] * 2;
  172.   build();
  173.   vector<M> dp(tc + 1);
  174.   vector<M> s {0};
  175.   M ans = 0;
  176.   dp[0] = 1;
  177.   for (int i = 1; i <= 4 * tc + 500; ++i) {
  178.     vector<M> ndp(tc + 1);
  179.     M cur = 0;
  180.     for (int j = 0; j <= tc; ++j) {
  181.       for (int k = 0; k < K; ++k) {
  182.         int to = trie[j][k];
  183.         ndp[to] += dp[j] * pw[cnt[to]];
  184.         cur += dp[j] * pw[cnt[to]];
  185.       }
  186.     }
  187.     dp = ndp;
  188.     s.push_back(cur);
  189.   }
  190.   if (n < (int)s.size()) {
  191.     cout << s[n] << '\n';
  192.     return;
  193.   }
  194.   cout << solve(berlekampMassey(s), s, n) << '\n';
  195. }
  196.  
  197. int main() {
  198.   ios::sync_with_stdio(false);
  199.   cin.tie(nullptr);
  200.   int t = 1;
  201.   // cin >> t;
  202.   while(t--) {
  203.     solve();
  204.   }
  205. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement