Codeforces-1106F:Lunar New Year and a Recursive Sequence(矩阵快速幂+BSGS)

F. Lunar New Year and a Recursive Sequence
time limit per test3 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
Lunar New Year is approaching, and Bob received a gift from his friend recently — a recursive sequence! He loves this sequence very much and wants to play with it.

Let f 1 , f 2 , … , f i , … f_1,f_2,…,f_i,… f1,f2,,fi, be an infinite sequence of positive integers. Bob knows that for i > k , f i i>k, f_i i>k,fi can be obtained by the following recursive equation:

f i = ( f i − 1 b 1 ⋅ f i − 2 b 2 ⋅ ⋯ ⋅ f i − k b k ) m o d p , fi=(f^{b_1}_{i−1}⋅f^{b_2}_{i−2}⋅⋯⋅f^{b_k}_{i−k})mod\quad p, fi=(fi1b1fi2b2fikbk)modp,
which in short is

f i = ( ∏ j = 1 k f i − j b j ) m o d p , f_i=(∏_{j=1}^{k}f^{b_j}_{i−j})mod\quad p, fi=(j=1kfijbj)modp,
where p=998244353 (a widely-used prime), b 1 , b 2 , … , b k b_1,b_2,…,b_k b1,b2,,bk are known integer constants, and x mod y denotes the remainder of x divided by y.

Bob lost the values of f 1 , f 2 , … , f k , f_1,f_2,…,f_k, f1,f2,,fk, which is extremely troublesome – these are the basis of the sequence! Luckily, Bob remembers the first k−1 elements of the sequence: f 1 = f 2 = … = f k − 1 = 1 f_1=f_2=…=f_{k−1}=1 f1=f2==fk1=1 and the n-th element: f n = m f_n=m fn=m. Please find any possible value of fk. If no solution exists, just tell Bob that it is impossible to recover his favorite sequence, regardless of Bob’s sadness.

Input
The first line contains a positive integer k ( 1 ≤ k ≤ 100 ) k (1≤k≤100) k(1k100), denoting the length of the sequence b 1 , b 2 , … , b k b_1,b_2,…,b_k b1,b2,,bk.

The second line contains k positive integers b 1 , b 2 , … , b k ( 1 ≤ b i &lt; p ) b_1,b_2,…,b_k (1≤b_i&lt;p) b1,b2,,bk(1bi<p).

The third line contains two positive integers n and m ( k &lt; n ≤ 1 0 9 , 1 ≤ m &lt; p ) (k&lt;n≤10^9, 1≤m&lt;p) (k<n109,1m<p), which implies f n = m f_n=m fn=m.

Output
Output a possible value of f k f_k fk, where f k f_k fk is a positive integer satisfying 1 ≤ f k &lt; p 1≤f_k&lt;p 1fk<p. If there are multiple answers, print any of them. If no such f k f_k fk makes f n = m f_n=m fn=m, output −1 instead.

It is easy to show that if there are some possible values of f k f_k fk, there must be at least one satisfying 1 ≤ f k &lt; p 1≤f_k&lt;p 1fk<p.

Examples
input
3
2 3 5
4 16
output
4
input
5
4 7 1 5 6
7 14187219
output
6
input
8
2 3 5 6 1 7 9 10
23333 1
output
1
input
1
2
88888 66666
output
-1
input
3
998244352 998244352 998244352
4 2
output
-1
input
10
283 463 213 777 346 201 463 283 102 999
2333333 6263423
output
382480067

思路:由题意可知 f k Q = f n = m f_k^{Q}=f_n=m fkQ=fn=m,而Q可以由矩阵快速幂求得(因为是指数,可以根据拓展欧拉定理取模降幂)。

求得Q后,即是求 f k f_k fk使得 f k Q ≡ m ( m o d P ) f_k^{Q}\equiv m(mod\quad P) fkQm(modP),这个很难求出。
由于998244353的原根为3,所以由原根的性质,存在且唯一存在一个 t t t使得 3 t ≡ m ( m o d P ) 3^t\equiv m(mod\quad P) 3tm(modP);同理,存在且仅存在一个 s s s使得 3 s Q ≡ m ( m o d P ) 3^{sQ}\equiv m(mod\quad P) 3sQm(modP)

那么根据拓展欧拉定理,现在就是解方程组 s ∗ Q + y ∗ ( P − 1 ) = t s*Q+y*(P-1)=t sQ+y(P1)=t,那么 f k = 3 s f_k=3^s fk=3s

其中 t t t可以根据BSGS算法求得,解方程组用扩展欧几里德即可。

#include<bits/stdc++.h>
using namespace std;
const int MAX=1e5+10;
const int MOD=998244353;
const double PI=acos(-1.0);
typedef long long ll;
struct lenka{ll a[101][101];};
ll K,N,M;
ll b[110];
lenka cal(const lenka& A,const lenka& B)
{
    lenka C;
    memset(C.a,0,sizeof C.a);
    for(int i=0;i<K;i++)
    for(int j=0;j<K;j++)
    for(int k=0;k<K;k++)
    {
        C.a[i][j]+=A.a[i][k]*B.a[k][j]%(MOD-1);
        C.a[i][j]%=MOD-1;
    }
    return C;
}
ll POW(ll n)
{
    lenka a,res;
    memset(res.a,0,sizeof res.a);
    memset(a.a,0,sizeof a.a);
    for(int i=0;i<K;i++)res.a[i][i]=1;
    for(int i=0;i<K;i++)a.a[i][0]=b[i];
    for(int i=1;i<K;i++)a.a[i-1][i]=1;
    while(n)
    {
        if(n&1)res=cal(res,a);
        a=cal(a,a);
        n/=2;
    }
    return res.a[0][0];
}
ll POW(ll x,ll n)
{
    ll res=1;
    while(n)
    {
        if(n&1)res=res*x%MOD;
        x=x*x%MOD;
        n/=2;
    }
    return res;
}
ll BSGS()
{
    ll n=sqrt(MOD)+1;
    map<ll,ll>ma;
    for(int i=0;i<=n;i++)ma[POW(3,i*n)]=i*n;
    for(int i=0;i<=n;i++)
    {
        if(ma[M*POW(POW(3,i),MOD-2)%MOD])
        {
            return ma[M*POW(POW(3,i),MOD-2)%MOD]+i;
        }
    }
    return -1;
}
void exgcd(ll a,ll b,ll &gcd,ll &x,ll &y)
{
    if(b==0){x=1,y=0;gcd=a;}
    else{exgcd(b,a%b,gcd,y,x);y-=(a/b)*x;}
}
int main()
{
    cin>>K;
    for(int i=0;i<K;i++)scanf("%lld",&b[i]);
    cin>>N>>M;
    ll P=POW(N-K);
    ll T=BSGS();
    ll x,y,gcd;
    exgcd(P,MOD-1,gcd,x,y);
    if(T%gcd)puts("-1");
    else
    {
        x=(T/gcd*x%(MOD-1)+MOD-1)%(MOD-1);
        cout<<POW(3,x)<<endl;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值