已知\(f_i = \prod \limits_{j = 1}^k f_{i - j}^{b_j}\;mod\;998244353\),而且\(f_1, f_2, ..., f_{k - 1} = 1\),\(f_k = a\),已知\(f_n = m\),試求\(a\)ios
易知\(f_n = f_k^p\)spa
對於\(p\)知足遞推式\(g[i] = \sum \limits_{j = 1}^k b[j] * g[i - j]\)code
這是常係數線性遞推,因爲\(k \leq 100\),所以矩陣快速冪便可get
那麼問題就變爲了\(f_k^p = m(\;mod\;998244353)\),求\(f_k\)string
因爲\(998244353\)的原根爲\(3\),所以把\(m\)離散以後,能夠寫出方程it
令\(f_k = 3^s(mod\;998244353)\),\(m = 3^t\),那麼有\(3^{sp} = 3^t (mod\;998244353)\)io
由歐拉定理\(sp = t(mod\;998244352)\),而後解一下這個同餘方程class
有解則輸出,無解就無解stream
複雜度\(O(k^3 \log n + \sqrt{998244353})\)map
#include <map> #include <queue> #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define de double #define ll long long #define ri register int #define rep(io, st, ed) for(ri io = st; io <= ed; io ++) #define drep(io, ed, st) for(ri io = ed; io >= st; io --) #define gc getchar inline int read() { int p = 0, w = 1; char c = gc(); while(c > '9' || c < '0') { if(c == '-') w = -1; c = gc(); } while(c >= '0' && c <= '9') p = p * 10 + c - '0', c = gc(); return p * w; } const int sid = 105; const int mod = 998244353; const int g = 3; inline int mul(int a, int b) { return 1ll * a * b % mod; } inline int fp(int a, int k) { int ret = 1; for( ; k; k >>= 1, a = mul(a, a)) if(k & 1) ret = mul(ret, a); return ret; } int n, m, k, b[sid]; struct mtx { int f[sid][sid]; mtx() {} mtx(int flag) { if(flag == 0) { for(int i = 0; i < k; i ++) for(int j = 0; j < k; j ++) f[i][j] = 0; } if(flag == 1) { for(int i = 0; i < k; i ++) for(int j = 0; j < k; j ++) f[i][j] = (i == j) ? 1 : 0; } } int* operator [] (const int x) { return f[x]; } friend mtx operator * (mtx a, mtx b) { mtx c(0); for(int i = 0; i < k; i ++) for(int j = 0; j < k; j ++) for(int p = 0; p < k; p ++) c[i][j] = (c[i][j] + 1ll * a[i][p] * b[p][j] % (mod - 1)) % (mod - 1); return c; } } A, B; inline mtx fp(mtx a, int k) { mtx ret(1); for( ; k; k >>= 1, a = a * a) if(k & 1) ret = ret * a; return ret; } map <int, int> H; inline int BSGS(int A, int B) { H.clear(); H[1] = 0; int Ai = 1, Aj = 1, m = ceil(sqrt(mod)); for(ri i = 1; i < m; i ++) Ai = 1ll * Ai * A % mod, H[1ll * Ai * B % mod] = i; Ai = 1ll * Ai * A % mod; for(ri i = 1; i <= m; i ++) { Aj = 1ll * Aj * Ai % mod; if(H[Aj]) return 1ll * i * m - H[Aj]; } } inline int gcd(int a, int b) { return b ? gcd(b, a % b) : a; } inline void exgcd(int &x, int &y, int a, int b) { if(!b) { x = 1; y = 0; return; } exgcd(y, x, b, a % b); y -= a / b * x; } inline void Solve() { A[0][k - 1] = 1; rep (i, 0, k - 1) B[i][k - 1] = b[k - i]; rep (i, 0, k - 2) B[i + 1][i] = 1; A = A * fp(B, n - k); int p = A[0][k - 1], t = BSGS(g, m); if(t % gcd(p, mod - 1)) printf("-1\n"); else { int gd = gcd(p, mod - 1); int x, y, a = p, b = mod - 1; t /= gd; a /= gd; b /= gd; exgcd(x, y, a, b); x = (x + mod - 1) % (mod - 1); x = 1ll * x * t % (mod - 1); printf("%d\n", fp(g, x)); } } int main() { k = read(); rep(i, 1, k) b[i] = read(); n = read(); m = read(); Solve(); return 0; }