[模板]线性递推+BM

暴力版本:

  1 #include<bits/stdc++.h>
  2 #define mod 998244353
  3 using namespace std;
  4 typedef long long int ll;
  5 const int maxn=1E4+5;
  6 const int inf=2333333;
  7 
  8 ll A[maxn],B[maxn],tmp[maxn];
  9 vector<ll>wait[maxn];
 10 
 11 inline ll qpow(ll x,ll y)
 12 {
 13     ll ans=1,base=x;
 14     while(y)
 15     {
 16         if(y&1)
 17             ans=ans*base%mod;
 18         base=base*base%mod;
 19         y>>=1;
 20     }
 21     return ans;
 22 }
 23 struct linear
 24 {
 25     vector<ll>val,a;
 26     int fail[maxn],cnt;
 27     ll delta[maxn];
 28     inline void mul(ll*A,ll*B)
 29     {
 30         int k=a.size();
 31         for(int i=0;i<2*k;++i)
 32             tmp[i]=0;
 33         for(int i=0;i<k;++i)
 34             for(int j=0;j<k;++j)
 35                 tmp[i+j]=(tmp[i+j]+A[i]*B[j])%mod;
 36         for(int i=2*k-1;i>=k;--i)
 37             for(int j=0;j<k;++j)
 38                 tmp[i-j-1]=(tmp[i-j-1]+tmp[i]*a[j])%mod;
 39         for(int i=0;i<k;++i)
 40             A[i]=tmp[i];
 41     }
 42     void qpowA(ll*A,ll*B,ll k)
 43     {
 44         while(k)
 45         {
 46             if(k&1)
 47                 mul(A,B);
 48             mul(B,B);
 49             k>>=1;
 50         }
 51     }
 52     ll quickRecursion(ll n)
 53     {
 54         int k=a.size();
 55         if(n<k)
 56             return val[n];
 57         for(int i=0;i<k;++i)
 58             A[i]=B[i]=0;
 59         A[0]=1;
 60         B[1]=1;
 61         qpowA(A,B,n);
 62         ll ans=0;
 63         for(int i=0;i<k;++i)
 64             ans=(ans+A[i]*val[i])%mod;
 65         return ans;
 66     }
 67     void BM()
 68     {
 69         cnt=0;
 70         for(int i=0;i<(int)val.size();++i)
 71             wait[i].clear();
 72         for(int i=0;i<(int)val.size();++i)
 73         {
 74             delta[i]=val[i];
 75             for(int j=0;j<(int)wait[cnt].size();++j)
 76                 delta[i]=(delta[i]-wait[cnt][j]*val[i-j-1]%mod+mod)%mod;
 77             if(delta[i]==0)
 78                 continue;
 79             fail[cnt]=i;
 80             if(cnt==0)
 81             {
 82                 wait[++cnt].resize(i+1);
 83                 continue;
 84             }
 85             int len=i-fail[cnt-1]+wait[cnt-1].size(),pos=cnt-1;
 86             for(int j=0;j<cnt;++j)
 87                 if(i-fail[j]+(int)wait[j].size()<len)
 88                     len=i-fail[j]+wait[j].size(),pos=j;
 89             ll g=delta[i]*qpow(delta[fail[pos]],mod-2)%mod;
 90             ++cnt;
 91             wait[cnt]=wait[cnt-1];
 92             while((int)wait[cnt].size()<len)
 93                 wait[cnt].push_back(0);
 94             wait[cnt][i-fail[pos]-1]=(wait[cnt][i-fail[pos]-1]+g)%mod;
 95             for(int j=0;j<(int)wait[pos].size();++j)
 96                 wait[cnt][i-fail[pos]+j]=(wait[cnt][i-fail[pos]+j]-g*wait[pos][j]%mod+mod)%mod;
 97         }
 98         a.clear();
 99         a=wait[cnt];
100         for(int i=0;i<(int)a.size();++i)
101             cout<<a[i]<<" ";
102         cout<<endl;
103     }
104 }T;
105 int main()
106 {
107     ios::sync_with_stdio(false);
108     ll n,m;
109     cin>>n>>m;
110     for(int i=1;i<=n;++i)
111     {
112         ll x;
113         cin>>x;
114         T.val.push_back(x);
115     }
116     T.BM();
117     cout<<T.quickRecursion(m)<<endl;
118     return 0;
119 }
View Code

猜你喜欢

转载自www.cnblogs.com/GreenDuck/p/11335871.html