给出 f 1 = f 2 = ⋯ = f k − 1 = 1 f_1=f_2=\cdots=f_{k-1}=1 f1=f2=⋯=fk−1=1和 b 1 , b 2 ⋯ b k b_1,b_2\cdots b_k b1,b2⋯bk,还有递推方程
f i = f i − 1 b 1 f i − 2 b 2 ⋯ f i − k b k f_i=f_{i-1}^{b_1}f_{i-2}^{b_2}\cdots f_{i-k}^{b_k}\\ fi=fi−1b1fi−2b2⋯fi−kbk
问是否存在一个 f k f_k fk使得 f n ≡ m ( m o d p ) f_n\equiv m(mod~p) fn≡m(mod p)成立;
矩阵快速幂 + B S G S +BSGS +BSGS
因为 n n n很大,所以不能直接推出 f n f_n fn是 f k f_k fk的多少次方,观察递推式全是乘法,我们就想到用矩阵加速。
先推出矩阵。
假设 k = 4 k=4 k=4,则可以推出下面的式子。
f k = f k f k + 1 = f k b 1 f k − 1 b 2 f k − 2 b 3 f k − 3 b 4 = f k b 1 f k + 2 = f k + 1 b 1 f k b 2 f k − 1 b 3 f k − 2 b 4 = ( f k b 1 ) b 1 f k b 2 = f k b 1 2 + b 2 f k + 3 = f k + 2 b 1 f k + 1 b 2 f k b 3 f k − 1 b 4 = f k b 1 3 + 2 b 1 ∗ b 2 + b 3 f k + 4 = f k + 3 b 1 f k + 2 b 2 f k + 1 b 3 f k b 4 = f k b 1 4 + 3 b 1 2 b 2 + 2 b 1 b 3 + b 2 2 + b 4 f k + 5 = f k + 4 b 1 f k + 3 b 2 f k + 2 b 3 f k + 1 b 1 \begin{aligned} &f_k=f_k\\ &f_{k+1}=f_k^{b_1}f_{k-1}^{b_2}f_{k-2}^{b_3}f_{k-3}^{b_4}=f_k^{b_1}\\ &f_{k+2}=f_{k+1}^{b_1}f_k^{b_2}f_{k-1}^{b_3}f_{k-2}^{b_4}=(f_k^{b_1})^{b_1}f_k^{b_2}=f_k^{b_1^2+b_2}\\ &f_{k+3}=f_{k+2}^{b_1}f_{k+1}^{b_2}f_k^{b_3}f_{k-1}^{b_4}=f_k^{b_1^3+2b_1*b_2+b_3}\\ &f_{k+4}=f_{k+3}^{b_1}f_{k+2}^{b_2}f_{k+1}^{b_3}f_k^{b_4}=f_k^{b_1^4+3b_1^2b_2+2b_1b_3+b_2^2+b_4}\\ &f_{k+5}=f_{k+4}^{b_1}f_{k+3}^{b_2}f_{k+2}^{b_3}f_{k+1}^{b_1}\\ \end{aligned} fk=fkfk+1=fkb1fk−1b2fk−2b3fk−3b4=fkb1fk+2=fk+1b1fkb2fk−1b3fk−2b4=(fkb1)b1fkb2=fkb12+b2fk+3=fk+2b1fk+1b2fkb3fk−1b4=fkb13+2b1∗b2+b3fk+4=fk+3b1fk+2b2fk+1b3fkb4=fkb14+3b12b2+2b1b3+b22+b4fk+5=fk+4b1fk+3b2fk+2b3fk+1b1
我们可以看出每个 f i f_i fi都是由前 k k k个 f f f值推出来的,所以我们设 f i f_i fi的对应的 f k f_k fk的系数是 g i g_i gi
我们就能找到一个一维的矩阵乘法
[ g 4 , g 3 , g 2 , g 1 ] × [ b 1 b 2 b 3 b 4 ] = g 5 \left[ \begin{matrix} g_4,g_3,g_2,g_1 \end{matrix} \right]\times \left[ \begin{matrix} b_1\\b_2\\b_3\\b_4 \end{matrix} \right]=g_5 [g4,g3,g2,g1]×⎣⎢⎢⎡b1b2b3b4⎦⎥⎥⎤=g5
[ g 5 , g 4 , g 3 , g 2 ] × [ b 1 b 2 b 3 b 4 ] = g 6 \left[ \begin{matrix} g_5,g_4,g_3,g_2 \end{matrix} \right]\times \left[ \begin{matrix} b_1\\b_2\\b_3\\b_4 \end{matrix} \right]=g_6 [g5,g4,g3,g2]×⎣⎢⎢⎡b1b2b3b4⎦⎥⎥⎤=g6
所以我们把矩阵扩展到 k k k维,希望得到一个包含 g i g_i gi的矩阵乘以另一个矩阵得到包含形式相同且包含 g i + 1 g_{i+1} gi+1的矩阵,
推出:
[ g 7 g 6 g 5 g 4 g 6 g 5 g 4 g 3 g 5 g 4 g 3 g 2 g 4 g 3 g 3 g 1 ] × [ b 1 1 0 0 b 2 0 1 0 b 3 0 0 1 b 4 0 0 0 ] = [ g 8 g 7 g 6 g 5 g 7 g 6 g 5 g 4 g 6 g 5 g 4 g 3 g 5 g 4 g 3 g 2 ] \left[ \begin{matrix} g_7&g_6&g_5&g_4 \\g_6&g_5&g_4&g_3 \\g_5&g_4&g_3&g_2 \\g_4&g_3&g_3&g_1 \end{matrix} \right]\times \left[ \begin{matrix} b_1&1&0&0 \\b_2&0&1&0 \\b_3&0&0&1 \\b_4&0&0&0 \end{matrix} \right]=\left[\begin{matrix} g_8&g_7&g_6&g_5 \\g_7&g_6&g_5&g_4 \\g_6&g_5&g_4&g_3 \\g_5&g_4&g_3&g_2 \end{matrix} \right] ⎣⎢⎢⎡g7g6g5g4g6g5g4g3g5g4g3g3g4g3g2g1⎦⎥⎥⎤×⎣⎢⎢⎡b1b2b3b4100001000010⎦⎥⎥⎤=⎣⎢⎢⎡g8g7g6g5g7g6g5g4g6g5g4g3g5g4g3g2⎦⎥⎥⎤
通过 k = 4 k=4 k=4的特例,我们能够推出 k k k是范围内的任意矩阵。
我们就能推出 f n f_n fn是 f k f_k fk的多少次方,设 f n f_n fn = f k a =f_k^a =fka。
现在的问题是已知 a a a,求是否存在 f k f_k fk使 f k a ≡ m ( m o d p ) f_k^a\equiv m(mod~p) fka≡m(mod p)成立。
这个就是之前的 b s g s bsgs bsgs的进阶篇:进阶篇
#include
using namespace std;
typedef long long ll;
const int N = 1e2+10;
const int mod = 998244353;
vector<ll> a;
ll b[N], k;
struct matrix {
//矩阵
ll s[N][N];
matrix operator * (const matrix &t) {
//矩阵乘法
matrix tmp;
for(int i=1; i<=k; i++) {
for(int j=1; j<=k; j++) {
tmp.s[i][j] = 0;
for(int l=1; l<=k; l++) {
tmp.s[i][j] = (tmp.s[i][j] + s[i][l] * t.s[l][j] % (mod-1)) % (mod-1);
}
}
}
return tmp;
}
} A, I, B;
matrix mqpow(matrix t, ll y) {
//矩阵快速幂
matrix ans = I;
while(y) {
if(y & 1) ans = ans * t;
t = t * t;
y >>= 1;
}
return ans;
}
ll qpow(ll x, ll y) {
//快速幂
ll ans = 1;
while(y) {
if(y & 1) ans = ans * x % mod;
x = x * x % mod;
y >>= 1;
}
return ans;
}
ll G(ll p) {
//求原根,就是3,可以直接存下来,就不用再计算了。
vector<int> v;
ll phi = p-1, tmp = phi;
for(int i=2; 1ll*i*i<=tmp; i++) {
if(tmp % i == 0) {
v.push_back(i);
while(tmp % i == 0) tmp /= i;
}
}
if(tmp > 1) v.push_back(tmp);
for(int i=2; i<=phi; i++) {
int f = 1;
for(auto it : v) {
if(i % it == 0) {
f = 0;
break;
}
if(f) return i;
}
}
return -1;
}
unordered_map<ll, ll> mp;
ll bsgs(ll aaa, ll b, ll p) {
//经典bsgs
mp.clear();
if(aaa % p == 0 && b % p != 0) return -1;
int k = ceil(sqrt(p));
for(int i=0; i<=k; i++) {
mp[b] = i, b = b * aaa % mod;
}
ll aa = qpow(aaa, k), A = aa;
// cout << aa<< endl;
for(int i=1; i<=k; i++) {
if(mp[A]) return 1ll*i*k - mp[A];
A = A * aa % mod;
}
return -1;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
//预处理+输入
scanf("%lld", &k);
for(int i=1; i<=k; i++) I.s[i][i] = 1;
for(int i=1; i<=k; i++) {
scanf("%lld", &b[i]);
}
for(int i=1; i<k; i++) a.push_back(0);
a.push_back(1);
//构建矩阵
for(int i=1; i<=k; i++) {
ll tmp = 0;
for(int j=1; j<=k; j++) {
tmp = (tmp + b[j] * a[a.size()-j] % (mod-1)) % (mod-1);
}
a.push_back(tmp);
}
ll n, m, aa;
scanf("%lld%lld", &n, &m);
//判断是否已经算出指数大小。
if(n <= 2*k) {
aa = a[n-1] % (mod-1);
}
else {
//构造矩阵。
for(int j=1, i=a.size()-1; j<=k; j++, i--) {
int l = 1;
while(l <= k) {
A.s[j][l] = a[i-l+1];
// cout << i-l+1 << endl;
l++;
}
}
for(int i=1; i<=k; i++) {
for(int j=1; j<=k; j++) {
if(i == 1) B.s[j][i] = b[j];
else if(j == i-1) {
B.s[j][i] = 1;
}
}
}
A = A * mqpow(B, n-2*k);
aa = A.s[1][1]%(mod-1);
}
//求原根+bsgs。
ll g = G(mod);
ll ans = bsgs(qpow(g, aa), m, mod);
if(ans != -1) cout << qpow(g, ans);
else cout << -1 << endl;
return 0;
}