CF1106F Lunar New Year and a Recursive Sequence - [题解]

题目大意:

给你一个序列 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=1kfijbj)mod p

其中 f 1 = f 2 = ⋯ = f k − 1 = 1 f_1=f_2=\cdots=f_{k-1}=1 f1=f2==fk1=1,且 k k k b 1 ∼ k b_{1\sim k} b1k都是已知的。现在你还知道 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} 010000100001bkbk1bk2b1

那么初始的向量就为指数了,为 [ 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=f1k1=1

注意这里是指数,所以取模就根据欧拉定理,对 p − 1 p-1 p1取模了。

我们这样就能得到 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 0998244352的所有数字,所以我们假设 3 t ≡ m , 3 s ≡ f k 3^t\equiv m,3^s\equiv f_k 3tm,3sfk,那么可以得到 3 s w ≡ 3 t 3^{sw}\equiv 3^t 3sw3t,根据欧拉定理又可以知道 s w ≡ t ( m o d   p − 1 ) sw\equiv t({\rm mod}\ p-1) swt(mod p1),所以用 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

VictoryCzt

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值