- 【题目地址】
题目大意:
给你一个序列 f f f,我们可以知道:
f i = ( ∏ j = 1 k f i − j b j ) m o d p f_i=\left(\prod_{j=1}^kf_{i-j}^{b_j}\right){\rm mod}\ p fi=(j=1∏kfi−jbj)mod p
其中 f 1 = f 2 = ⋯ = f k − 1 = 1 f_1=f_2=\cdots=f_{k-1}=1 f1=f2=⋯=fk−1=1,且 k k k和 b 1 ∼ k b_{1\sim k} b1∼k都是已知的。现在你还知道 f n = m ( n > k ) f_n=m(n>k) fn=m(n>k),问你是否有满足条件的 f k f_k fk,有则输出一种合法的可能的 f k f_k fk,否则输出 − 1 -1 −1(其中 p = 998244353 p=998244353 p=998244353)。
首先,我们不知道 f k f_k fk,要求它,所以将它的值设为 x x x,那么原序列的前 k k k个就是: [ 1 , 1 , 1 , 1 , ⋯   , x ] [1,1,1,1,\cdots,x] [1,1,1,1,⋯,x],根据公式我们可以发现, f k + 1 = x b 1 , f k + 2 = x b 1 2 + b 2 , ⋯ f_{k+1}=x^{b_1},f_{k+2}=x^{b_1^2+b_2},\cdots fk+1=xb1,fk+2=xb12+b2,⋯,所以我们可以递推出 f n = x w f_n=x^w fn=xw,但是 n n n有点大,所以我们考虑用矩阵加速:
我们构造这样的一个矩阵:
[ 0 0 ⋯ 0 b k 1 0 ⋯ 0 b k − 1 0 1 ⋯ 0 b k − 2 ⋮ ⋮ ⋱ ⋮ ⋮ 0 0 ⋯ 1 b 1 ] \begin{bmatrix}0&0&\cdots&0&b_k\\ 1&0&\cdots&0&b_{k-1}\\0&1&\cdots&0&b_{k-2}\\\vdots&\vdots&\ddots&\vdots&\vdots\\0&0&\cdots&1&b_1\end{bmatrix} ⎣⎢⎢⎢⎢⎢⎡010⋮0001⋮0⋯⋯⋯⋱⋯000⋮1bkbk−1bk−2⋮b1⎦⎥⎥⎥⎥⎥⎤
那么初始的向量就为指数了,为 [ 0 , 0 , 0 , ⋯   , 1 ] [0,0,0,\cdots,1] [0,0,0,⋯,1](最后一个就是开始表示 x 1 = f k x^1=f_k x1=fk,其他的开始就是 x 0 = f 1 ∼ k − 1 = 1 x^0=f_{1\sim k-1}=1 x0=f1∼k−1=1)
注意这里是指数,所以取模就根据欧拉定理,对 p − 1 p-1 p−1取模了。
我们这样就能得到 f n = f k w = m f_n=f_k^w=m fn=fkw=m
由于 998244353 998244353 998244353这个质数的原根为 3 3 3,那么 3 3 3的幂次在模其意义下可以表示出 0 ∼ 998244352 0\sim 998244352 0∼998244352的所有数字,所以我们假设 3 t ≡ m , 3 s ≡ f k 3^t\equiv m,3^s\equiv f_k 3t≡m,3s≡fk,那么可以得到 3 s w ≡ 3 t 3^{sw}\equiv 3^t 3sw≡3t,根据欧拉定理又可以知道 s w ≡ t ( m o d p − 1 ) sw\equiv t({\rm mod}\ p-1) sw≡t(mod p−1),所以用 e x g c d exgcd exgcd便可以求出 s s s了,那么 f k f_k fk也就知道了。
所以我们用 B S G S BSGS BSGS算法求 t t t,矩阵快速幂求 w w w, e x g c d exgcd exgcd求 s s s,中途判断一下有没有解就可以做出来了。
复杂度 O ( k 3 l o g n + p ) O(k^3logn+\sqrt{p}) O(k3logn+p)
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<tr1/unordered_map>
#define ll long long
using namespace std;
using namespace tr1;
const int M=1e6+10,N=101;
const ll Mod=998244353,G=3;
int n,K;ll B[M],m;
struct Matrix{
ll m[N][N];
void clear(){memset(m,0,sizeof(m));}
void init(){
clear();for(int i=1;i<K;i++)m[i+1][i]=1;
for(int i=K;i>=1;i--)m[i][K]=B[K-i+1]%(Mod-1);
}
}mat,Ls1;
struct Vector{
ll m[N];
void clear(){memset(m,0,sizeof(m));}
void init(){
for(int i=1;i<K;i++)m[i]=0;m[K]=1;
}
}V,Ls2;
Matrix operator *(const Matrix &a,const Matrix &b){
for(int i=1;i<=K;i++){
for(int j=1;j<=K;j++){
Ls1.m[i][j]=0;
for(int k=1;k<=K;k++){
(Ls1.m[i][j]+=a.m[i][k]*b.m[k][j]%(Mod-1))%=(Mod-1);
}
}
}
return Ls1;
}
Vector operator *(const Vector &a,const Matrix &b){
for(int i=1;i<=K;i++){
Ls2.m[i]=0;
for(int j=1;j<=K;j++){
(Ls2.m[i]+=a.m[j]*b.m[j][i]%(Mod-1))%=(Mod-1);
}
}
return Ls2;
}
ll fpow(ll a){
V.init();mat.init();
for(;a;a>>=1,mat=mat*mat)
if(a&1)V=V*mat;
return V.m[K];
}
ll work(){return fpow(n-K);}
ll fpow(ll a,ll b){
ll res=1;
for(;b;b>>=1,a=(a*a)%Mod){
if(b&1)res=(res*a)%Mod;
}
return res;
}
unordered_map <ll,ll> mp;
ll BSGS(ll a,ll b){
ll now=31596,res=b,ans=0;mp[b]=0;
for(ll i=1;i<=now;i++){res=res*a%Mod;mp[res]=i;}
a=fpow(a,now);if(!a){return !b?1:-1;}
res=1;
for(ll i=1,j;i<=now;i++){
res=res*a%Mod;
if(mp.count(res)){
j=mp[res];
ans=(i*now-j)%Mod;
if(ans<0)ans+=Mod;
return ans;
}
}
return -1;
}
ll exgcd(ll a,ll b,ll &x,ll &y){
if(!b){x=1;y=0;return a;}
ll t=exgcd(b,a%b,y,x);
y-=x*(a/b);return t;
}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
int main(){
scanf("%d",&K);
for(int i=1;i<=K;i++)scanf("%lld",&B[i]);
scanf("%d%lld",&n,&m);
ll now=BSGS(G,m),tw=work(),x,y;
if(now==-1){puts("-1");return 0;}
ll w=gcd(tw,Mod-1);
if(now%w){puts("-1");return 0;}
tw/=w;ll ww=(Mod-1)/w;now/=w;
exgcd(tw,ww,x,y);
x%=(Mod-1);if(x<0)x+=Mod-1;
printf("%lld\n",fpow(G,now*x%(Mod-1)));
return 0;
}