可以发现, (f) 数列的每一项都可以写成 (f_k^p) 的形式,所以可以直接在指数上跑矩阵快速幂即可。记第 (n) 项的系数为 (q),则现在相当于解方程 (x^q=mpmod p)。
由于 (p) 是质数,所以我们可以找到模 (p) 意义下的原根 (g),设 (g^t=x,g^u=m),代入得 (g^{tq}=g^u),取离散对数得 (tqequiv upmod{m-1})(根据欧拉定理),然后跑个 exgcd 就做完了。
代码:
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<map>
#include<cmath>
#define int long long
using namespace std;
const int M=998244353,N=109,_M=M-1;
int k,b[N],n,m;
map <int,int> Map;
struct Matrix
{
int c[N][N];
void clear()
{
for (int i=1;i<=k;i++)
for (int j=1;j<=k;j++)
c[i][j]=0;
}
Matrix operator * (const Matrix A)const
{
Matrix B;B.clear();
for (int i=1;i<=k;i++)
for (int j=1;j<=k;j++)
for (int l=1;l<=k;l++)
B.c[i][j]=(B.c[i][j]+c[i][l]*A.c[l][j]%_M)%_M;
return B;
}
};
int ksm(Matrix A,int b)
{
Matrix res;res.clear();
for (int i=1;i<=k;i++)
res.c[i][i]=1;
while(b)
{
if(b&1)
res=res*A;
b>>=1,A=A*A;
}
return res.c[k][k];
}
int ksm(int a,int b)
{
int res=1;
while(b)
{
if(b&1)
res=res*a%M;
b>>=1,a=a*a%M;
}
return res;
}
int read()
{
int x=0;
char c=getchar();
while(c<'0'||c>'9')
c=getchar();
while(c>='0'&&c<='9')
x=x*10+c-'0',c=getchar();
return x;
}
void init()
{
k=read();
for (int i=1;i<=k;i++)
b[i]=read();
n=read(),m=read();
}
int BSGS(int a,int b)
{
Map.clear();
int Sqr=ceil(sqrt(M));
int j=1;
for (int i=0;i<Sqr;i++)
Map[b*j%M]=i,j=j*a%M;
for (int i=1,l=j;i<=Sqr;i++,l=l*j%M)
if(Map[l])
return i*Sqr-Map[l];
return -1;
}
void Exgcd(int a,int b,int &d,int &x,int &y)
{
if(b==0)
{
x=1,y=0,d=a;
return;
}
Exgcd(b,a%b,d,x,y);
int t=x;
x=y,y=t-a/b*y;
}
void work()
{
Matrix A;A.clear();
for (int i=1;i<k;i++)
A.c[i][i+1]=1;
for (int i=1;i<=k;i++)
A.c[k][i]=b[k-i+1];
int ans=ksm(A,n-k);
int X=BSGS(3,m),d,x,y;
Exgcd(ans,_M,d,x,y);
if(X%d!=0)
{
puts("-1");
return;
}
int q=_M/d;
x=(x*(X/d)%q+q)%q;
printf("%lld
",ksm(3,x));
}
signed main()
{
init();
work();
return 0;
}