给出一个k阶递推式
(
m
o
d
998244353
)
\pmod{998244353}
(mod998244353),
f
[
1...
k
−
1
]
=
1
,
f
[
n
]
=
m
f[1...k-1] = 1,f[n] =m
f[1...k−1]=1,f[n]=m
求
f
[
k
]
f[k]
f[k]
这个递推式显然让人想两边同时求一个对数。
令
g
[
i
]
=
log
f
[
i
]
g[i] = \log f[i]
g[i]=logf[i]
有
g
[
i
]
=
∑
j
=
1
k
b
[
j
]
g
[
i
−
j
]
g[i] = \sum_{j=1}^k b[j]g[i-j]
g[i]=∑j=1kb[j]g[i−j]
常系数线性递推???
然后发现
g
[
1...
k
−
1
]
=
0
g[1...k-1] = 0
g[1...k−1]=0
g
[
n
]
g[n]
g[n]又是
g
[
1...
k
]
g[1...k]
g[1...k]的线性组合。
那么设
g
[
n
]
=
∑
i
=
1
k
c
[
i
]
∗
g
[
i
]
g[n] = \sum_{i=1}^kc[i] * g[i]
g[n]=∑i=1kc[i]∗g[i]
可以发现
g
[
n
]
=
c
[
k
]
∗
g
[
k
]
g[n] = c[k] * g[k]
g[n]=c[k]∗g[k]
c[k]可以通过特征多项式+多项式取模来计算矩阵快速幂来计算。
g[n]可以通过。。。好吧这里
log
\log
log的底数可以任意所以模意义下的
log
\log
log我们可以用998244353的原根3做底数,然后模意义下的
log
\log
log就可以用bsgs来
O
(
n
)
O(\sqrt n)
O(n)计算了。
然后就是同余方程:
c
[
k
]
∗
g
[
k
]
=
g
[
n
]
(
m
o
d
998244353
)
c[k] * g[k] = g[n] \pmod {998244353}
c[k]∗g[k]=g[n](mod998244353)
这个gcd一下就可以判断有无解。
exgcd一下就可以计算出一组解。
这个题好像就这么精彩的结束了?(好像可以把k开到
1
0
5
10^5
105的样子)
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));
}
}