1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
| #include <iostream> #include <cstdio> #include <cstring> #include <algorithm>
#define MOD 998244353 #define g 3
using namespace std;
typedef long long LL;
const int MAXK = 32000 + 10; const int MAXN = 1 << 20;
inline LL power (LL x, int p) { LL cnt = 1; while (p) { if (p & 1) cnt = cnt * x % MOD; x = x * x % MOD; p >>= 1; } return cnt; } const LL invg = power (g, MOD - 2);
int oppo[MAXN]= {0}, limit; void NTT (LL* a, int inv) { for (int i = 0; i < limit; i ++) if (i < oppo[i]) swap (a[i], a[oppo[i]]); for (int mid = 1; mid < limit; mid <<= 1) { LL ome = power (inv == 1 ? g : invg, (MOD - 1) / (mid << 1)); for (int n = mid << 1, j = 0; j < limit; j += n) { LL x = 1; for (int k = 0; k < mid; k ++, x = x * ome % MOD) { LL a1 = a[j + k], xa2 = x * a[j + mid + k] % MOD; a[j + k] = (a1 + xa2) % MOD; a[j + mid + k] = (a1 - xa2 + MOD) % MOD; } } } } LL A[MAXN], B[MAXN], O[MAXN]= {0}; void mul (LL* X, LL* Y, int fn, int fm, int rst) { int n, lim; for (n = 1, lim = 0; n <= fn + fm; n <<= 1, lim ++); limit = n; for (int i = 0; i < limit; i ++) oppo[i] = (oppo[i >> 1] >> 1) | ((i & 1) << (lim - 1)); for (int i = 0; i < limit; i ++) A[i] = B[i] = 0; for (int i = 0; i <= fn; i ++) A[i] = X[i]; for (int i = 0; i <= fm; i ++) B[i] = Y[i]; NTT (A, 1), NTT (B, 1); for (int i = 0; i < limit; i ++) A[i] = A[i] * B[i] % MOD; NTT (A, - 1); LL invn = power (n, MOD - 2); for (int i = 0; i <= rst; i ++) X[i] = A[i] * invn % MOD; for (int i = rst + 1; i <= fn + fm; i ++) X[i] = 0; } void inverse (int deg, LL* a) { if (deg == 1) { a[0] = power (O[0], MOD - 2); return ; } inverse ((deg + 1) >> 1, a); int n, lim; for (n = 1, lim = 0; n <= deg << 1; n <<= 1, lim ++); limit = n; for (int i = 0; i < limit; i ++) oppo[i] = (oppo[i >> 1] >> 1) | ((i & 1) << (lim - 1)); for (int i = 0; i < limit; i ++) A[i] = B[i] = 0; for (int i = 0; i < deg; i ++) A[i] = O[i]; for (int i = 0; i < deg << 1; i ++) B[i] = a[i]; NTT (A, 1), NTT (B, 1); for (int i = 0; i < limit; i ++) B[i] = B[i] * ((2ll - A[i] * B[i] % MOD + MOD) % MOD) % MOD; NTT (B, - 1); LL invn = power (n, MOD - 2); for (int i = 0; i < deg; i ++) a[i] = B[i] * invn % MOD; } LL R[MAXN], INVG[MAXN]= {0}; void prep (LL* G, int n, int m) { for (int i = 0; i <= m; i ++) O[i] = G[i]; reverse (O, O + m + 1); for (int i = n - m + 2; i <= m; i ++) O[i] = 0; inverse (n - m + 1, INVG); } void PolyMod (LL* F, LL* G, int n, int m){ for (int i = 0; i <= n; i ++) R[i] = F[i]; reverse (R, R + n + 1); mul (R, INVG, n, n - m + 1, n); reverse (R, R + n - m + 1); for (int i = n - m + 1; i <= n; i ++) R[i] = 0; mul (R, G, n - m, m, n); for (int i = 0; i < m; i ++) R[i] = (F[i] - R[i] + MOD) % MOD; for (int i = 0; i <= n; i ++) { F[i] = i < m ? R[i] : 0; R[i] = 0; } }
int N, K, L; LL F[MAXK]= {0}, h[MAXK]= {0};
LL X[MAXN]= {0}, ANS[MAXN]= {0}; void PolyPow (int p) { while (p) { if (p & 1) { mul (ANS, X, K - 1, K - 1, L); PolyMod (ANS, F, L, K); } mul (X, X, K - 1, K - 1, L); PolyMod (X, F, L, K); p >>= 1; } }
inline int getnum () { int num = 0; char ch = getchar (); bool isneg = false; while (! isdigit (ch)) { if (ch == '-') isneg = true; ch = getchar (); } while (isdigit (ch)) num = (num << 3) + (num << 1) + ch - '0', ch = getchar (); return isneg ? - num : num; }
int main () { N = getnum (), K = getnum (); L = (K - 1) << 1; for (int i = 1; i <= K; i ++) F[K - i] = (MOD - getnum () % MOD) % MOD; for (int i = 0; i < K; i ++) h[i] = getnum () % MOD; F[K] = X[1] = ANS[0] = 1; prep (F, L, K); PolyPow (N); LL ans = 0; for (int i = 0; i < K; i ++) ans = (ans + ANS[i] * h[i] % MOD + MOD) % MOD; cout << ans << endl;
return 0; }
|