版权声明:本文为博主原创文章,未经博主允许必须转载。 https://blog.csdn.net/qq_35950004/article/details/86739330
给出一个k阶递推式
,
求
这个递推式显然让人想两边同时求一个对数。
令
有
常系数线性递推???
然后发现
又是
的线性组合。
那么设
可以发现
c[k]可以通过特征多项式+多项式取模来计算矩阵快速幂来计算。
g[n]可以通过。。。好吧这里
的底数可以任意所以模意义下的
我们可以用998244353的原根3做底数,然后模意义下的
就可以用bsgs来
计算了。
然后就是同余方程:
这个gcd一下就可以判断有无解。
exgcd一下就可以计算出一组解。
这个题好像就这么精彩的结束了?(好像可以把k开到
的样子)
AC Code:
#include<cstdio>
#include<algorithm>
#include<map>
#include<cstring>
#define maxn 105
#define mod 998244352
#define Mod 998244353
#define S 100005
using namespace std;
map<int,int>mp;
int k,n,m;
struct mat
{
int a[maxn][maxn];
mat(){memset(a,0,sizeof a);}
mat operator *(const mat &B)const
{
mat ret;
for(int i=0;i<k;i++)
for(int j=0;j<k;j++) if(a[i][j])
for(int p=0;p<k;p++) if(B.a[j][p])
ret.a[i][p] = (ret.a[i][p] + 1ll * a[i][j] * B.a[j][p]) % mod;
return ret;
}
}b;
mat Pow(mat base,int p)
{
mat ret;
for(int i=0;i<k;i++)
ret.a[i][i] = 1;
for(;p;p>>=1,base=base*base)
if(p&1)
ret = ret * base;
return ret;
}
int Pow(int base,int p)
{
int ret = 1;
for(;p;p>>=1,base=1ll*base*base%998244353)
if(p&1)
ret = ret * 1ll * base % 998244353;
return ret;
}
void exgcd(int a,int b,int &x,int &y,int &gcd)
{
if(!b) gcd=a,x=1,y=0;
else exgcd(b,a%b,y,x,gcd),
y-=a/b*x;
}
int main()
{
scanf("%d",&k);
for(int i=0;i<k;i++) scanf("%d",&b.a[0][i]);
for(int i=1;i<k;i++) b.a[i][i-1] = 1;
scanf("%d%d",&n,&m);
n-=k;
b = Pow(b,n);
int tmp = b.a[0][0];
int G = 3;
for(int i=0,s=1;i<S;i++,s=1ll*s*G%998244353)
mp[s] = i;
int Gp = Pow(Pow(G,S),Mod-2);
int zb = 0;
for(int i=0,s=m,tmp;i<S;i++,s=1ll*s*Gp%998244353)
if(mp.count(s))
{
zb = mp[s] + i * S;
break;
}
int x,y,gcd;
exgcd(tmp,998244352,x,y,gcd);
if(zb % gcd) puts("-1");
else
{
zb /= gcd;
x = 1ll * x * zb % mod;
printf("%d\n",Pow(3,(x+mod)%mod));
}
}