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

版权声明:http://blog.csdn.net/Mitsuha_。 https://blog.csdn.net/Mitsuha_/article/details/86765400

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,… be an infinite sequence of positive integers. Bob knows that for i > k , f i i>k, f_i 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,
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,
where p=998244353 (a widely-used prime), b 1 , b 2 , , b k b_1,b_2,…,b_k 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, 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 and the n-th element: f n = m f_n=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) , denoting the length of the sequence b 1 , b 2 , , b k b_1,b_2,…,b_k .

The second line contains k positive integers b 1 , b 2 , , b k ( 1 b i < p ) b_1,b_2,…,b_k (1≤b_i<p) .

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

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

It is easy to show that if there are some possible values of f k f_k , there must be at least one satisfying 1 f k < p 1≤f_k<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 ,而Q可以由矩阵快速幂求得(因为是指数,可以根据拓展欧拉定理取模降幂)。

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

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

其中 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;
}

猜你喜欢

转载自blog.csdn.net/Mitsuha_/article/details/86765400