一、模板
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<bitset>
#define ll long long
#define llu unsigned ll
#define pr make_pair
#define pb push_back
//#define lc (cnt<<1)
//#define rc (cnt<<1|1)
using namespace std;
const int inf=0x3f3f3f3f;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const double dnf=1e15;
const int mod=998244353;
const double eps=1e-8;
const int maxn=550;
namespace linear_seq
{
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef pair<int,int> PII;
const int N=10010;
ll res[N],base[N],c[N],md[N];
vector<int> Md;
const ll mod=998244353;
ll powmod(ll a,ll b)
{
ll res=1;
a%=mod;
for(;b;b>>=1)
{
if(b&1)
res=res*a%mod;
a=a*a%mod;
}
return res;
}
void mul(ll *a,ll *b,int k)
{
for(int i=0;i<k+k;++i) c[i]=0;
for(int i=0;i<k;++i)
if(a[i])for(int j=0;j<k ;++j)
c[i+j]=(c[i+j]+a[i]*b[j])%mod;
for (int i=k+k-1;i>=k;i--)
if(c[i])for(int j=0;j<(int)Md.size();++ j)
c[i-k+Md[j]]=(c[i-k+Md[j]]-c[i]*md[Md[j]])%mod;
for(int i=0;i<k;++i) a[i]=c[i];
}
int solve(ll n,VI a,VI b)
{
ll ans=0,pnt=0;
int k=SZ(a);
for(int i=0;i<k;++i) md[k-1-i]=-a[i];
md[k]=1;Md.clear();
for(int i=0;i<k;++i)
if(md[i]!=0)Md.push_back(i);
for(int i=0;i<k;++i) res[i]=base[i]=0;
res[0]=1;
while ((1ll<<pnt)<=n)
pnt++;
for (int p=pnt;p>=0;p--)
{
mul(res,res,k);
if ((n>>p)&1)
{
for (int i=k-1;i>=0;i--) res[i+1]=res[i];
res[0]=0;
for(int j=0;j<(int)Md.size();++ j)
res[Md[j]]=(res[Md[j]]-res[k]*md[Md[j]])%mod;
}
}
for(int i=0;i<k;i++) ans=(ans+res[i]*b[i])%mod;
if (ans<0) ans+=mod;
return ans;
}
VI BM(VI s)
{
VI C(1,1),B(1,1);
int L=0,m=1,b=1;
for(int n=0;n<(int)s.size();++n)
{
ll d=0;
for(int i=0;i<L+1;++ i)
d=(d+(ll)C[i]*s[n-i])%mod;
if(d==0) ++m;
else if(2*L<=n)
{
VI T=C;
ll c=mod-d*powmod(b,mod-2)%mod;
while (SZ(C)<SZ(B)+m)C.push_back(0);
for(int i=0;i<(int)B.size();++i) C[i+m]=(C[i+m]+c*B[i])%mod;
L=n+1-L; B=T; b=d; m=1;
}
else
{
ll c=mod-d*powmod(b,mod-2)%mod;
while (SZ(C)<SZ(B)+m)C.push_back(0);
for(int i=0;i<(int)B.size();++ i) C[i+m]=(C[i+m]+c*B[i])%mod;
++m;
}
}
return C;
}
ll gao(VI a,ll n)
{
VI c=BM(a);
c.erase(c.begin());
for(int i=0;i<(int)c.size();++i) c[i]=(mod-c[i])%mod;
return (ll)solve(n,c,VI(a.begin(),a.begin()+SZ(c)));
}
};
int main()
{
int n,k;
scanf("%d%d",&k,&n);//给定前k项求第n项
vector<int>vc;//项数越多越好
for(int i=1;i<=k;i++)
{
int x;
scanf("%d",&x);
vc.pb(x);
}
printf("%lld\n",linear_seq::gao(vc,n-1));
return 0 ;
}
二、P5487 【模板】Berlekamp-Massey算法:
注意:这里的Pm其实是第m+1项。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<bitset>
#define ll long long
#define llu unsigned ll
#define pr make_pair
#define pb push_back
//#define lc (cnt<<1)
//#define rc (cnt<<1|1)
using namespace std;
const int inf=0x3f3f3f3f;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const double dnf=1e15;
const int mod=998244353;
const double eps=1e-8;
const int maxn=550;
namespace linear_seq
{
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef pair<int,int> PII;
const int N=10010;
ll res[N],base[N],c[N],md[N];
vector<int> Md;
const ll mod=998244353;
ll powmod(ll a,ll b)
{
ll res=1;
a%=mod;
for(;b;b>>=1)
{
if(b&1)
res=res*a%mod;
a=a*a%mod;
}
return res;
}
void mul(ll *a,ll *b,int k)
{
for(int i=0;i<k+k;++i) c[i]=0;
for(int i=0;i<k;++i)
if(a[i])for(int j=0;j<k ;++j)
c[i+j]=(c[i+j]+a[i]*b[j])%mod;
for (int i=k+k-1;i>=k;i--)
if(c[i])for(int j=0;j<(int)Md.size();++ j)
c[i-k+Md[j]]=(c[i-k+Md[j]]-c[i]*md[Md[j]])%mod;
for(int i=0;i<k;++i) a[i]=c[i];
}
int solve(ll n,VI a,VI b)
{
ll ans=0,pnt=0;
int k=SZ(a);
for(int i=0;i<k;++i) md[k-1-i]=-a[i];
md[k]=1;Md.clear();
for(int i=0;i<k;++i)
if(md[i]!=0)Md.push_back(i);
for(int i=0;i<k;++i) res[i]=base[i]=0;
res[0]=1;
while ((1ll<<pnt)<=n)
pnt++;
for (int p=pnt;p>=0;p--)
{
mul(res,res,k);
if ((n>>p)&1)
{
for (int i=k-1;i>=0;i--) res[i+1]=res[i];
res[0]=0;
for(int j=0;j<(int)Md.size();++ j)
res[Md[j]]=(res[Md[j]]-res[k]*md[Md[j]])%mod;
}
}
for(int i=0;i<k;i++) ans=(ans+res[i]*b[i])%mod;
if (ans<0) ans+=mod;
return ans;
}
VI BM(VI s)
{
VI C(1,1),B(1,1);
int L=0,m=1,b=1;
for(int n=0;n<(int)s.size();++n)
{
ll d=0;
for(int i=0;i<L+1;++ i)
d=(d+(ll)C[i]*s[n-i])%mod;
if(d==0) ++m;
else if(2*L<=n)
{
VI T=C;
ll c=mod-d*powmod(b,mod-2)%mod;
while (SZ(C)<SZ(B)+m)C.push_back(0);
for(int i=0;i<(int)B.size();++i) C[i+m]=(C[i+m]+c*B[i])%mod;
L=n+1-L; B=T; b=d; m=1;
}
else
{
ll c=mod-d*powmod(b,mod-2)%mod;
while (SZ(C)<SZ(B)+m)C.push_back(0);
for(int i=0;i<(int)B.size();++ i) C[i+m]=(C[i+m]+c*B[i])%mod;
++m;
}
}
return C;
}
ll gao(VI a,ll n)
{
VI c=BM(a);
c.erase(c.begin());
for(int i=0;i<(int)c.size();++i) c[i]=(mod-c[i])%mod;
//vector c 保存的是最短递推式的系数
for(int i=0;i<(int)c.size();++i)
{
if(i!=0) putchar(' ');
printf("%d",c[i]);
}
putchar('\n');
return (ll)solve(n,c,VI(a.begin(),a.begin()+SZ(c)));
}
};
int main()
{
int n,m;
scanf("%d%d",&n,&m);
vector<int>vc;
for(int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
vc.pb(x);
}
printf("%lld\n",linear_seq::gao(vc,m));
return 0 ;
}
三、一个板子搞定模数为质数的情况与模数不为质数的情况。
(1)模数任意:
牛客:The power of Fibonacci
注意:序列是从第0项开始的。
斐波那契数列前n项m次幂和是一个m+2阶的线性递推方程。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<bitset>
#define ll long long
#define llu unsigned ll
#define pr make_pair
#define pb push_back
//#define lc (cnt<<1)
//#define rc (cnt<<1|1)
using namespace std;
const int inf=0x3f3f3f3f;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const double dnf=1e15;
const int mod=1000000000;
const double eps=1e-8;
const int maxn=550;
namespace linear_seq
{
#define SZ(x) ((ll)(x).size())
#define FOR(i,a,b) for(int i(a);i<=(b);++i)
#define FOL(i,a,b) for(int i(a);i>=(b);--i)
typedef vector<ll> VI;
using vec = std::vector<ll>;
const int N=10010;
ll res[N],base[N],c[N],md[N];
const ll mod = 1000000000;
vector<int> Md;
ll powmod(ll a,ll b)
{
ll res=1LL;
while(b)
{
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
void mul(ll *a,ll *b,int k)
{
for(int i=0;i<k+k;++i) c[i]=0;
for(int i=0;i<k;++i)
if(a[i])for(int j=0;j<k ;++j)
c[i+j]=(c[i+j]+a[i]*b[j])%mod;
for (int i=k+k-1;i>=k;i--)
if(c[i])for(int j=0;j<(int)Md.size();++ j)
c[i-k+Md[j]]=(c[i-k+Md[j]]-c[i]*md[Md[j]])%mod;
for(int i=0;i<k;++i) a[i]=c[i];
}
int solve(ll n,VI a,VI b)
{ // a 系数 b 初值 b[n+1]=a[0]*b[n]+...
ll ans=0,pnt=0;
int k=SZ(a);
for(int i=0;i<k;++i) md[k-1-i]=-a[i];
md[k]=1;Md.clear();
for(int i=0;i<k;++i) if(md[i]!=0)Md.push_back(i);
for(int i=0;i<k;++i) res[i]=base[i]=0;
res[0]=1;
while ((1ll<<pnt)<=n) pnt++;
for (int p=pnt;p>=0;p--)
{
mul(res,res,k);
if ((n>>p)&1)
{
for (int i=k-1;i>=0;i--) res[i+1]=res[i];
res[0]=0;
for(int j=0;j<(int)Md.size();++j)
res[Md[j]]=(res[Md[j]]-res[k]*md[Md[j]])%mod;
}
}
for(int i=0;i<k;i++) ans=(ans+res[i]*b[i])%mod;
if (ans<0) ans+=mod;
return ans;
}
VI BM(VI s)
{
VI C(1,1),B(1,1);
int L=0,m=1,b=1;
for(int n=0;n<(int)s.size();++n)
{
ll d=0;
for(int i=0;i<L+1;++ i) d=(d+(ll)C[i]*s[n-i])%mod;
if(d==0) ++m;
else if(2*L<=n)
{
VI T=C;
ll c=mod-d*powmod(b,mod-2)%mod;
while (SZ(C)<SZ(B)+m)C.push_back(0);
for(int i=0;i<(int)B.size();++i) C[i+m]=(C[i+m]+c*B[i])%mod;
L=n+1-L; B=T; b=d; m=1;
}
else
{
ll c=mod-d*powmod(b,mod-2)%mod;
while (SZ(C)<SZ(B)+m)C.push_back(0);
for(int i=0;i<(int)B.size();++ i) C[i+m]=(C[i+m]+c*B[i])%mod;
++m;
}
}
return C;
}
static void extand(vec &a, size_t d, ll value=0)
{
if (d<=a.size()) return;
a.resize(d, value);
}
static void exgcd(ll a, ll b, ll &g, ll &x, ll &y)
{
if (!b) x=1,y=0,g=a;
else
{
exgcd(b,a%b,g,y,x);
y-=x*(a/b);
}
}
static ll crt(const vec &c, const vec &m)
{
int n=c.size();
ll M=1,ans=0;
for(int i=0;i<n;++i) M*=m[i];
for(int i=0;i<n;++i)
{
ll x,y,g,tm=M/m[i];
exgcd(tm,m[i],g,x,y);
ans=(ans+tm*x*c[i]%M)%M;
}
return (ans+M)%M;
}
static vec ReedsSloane(const vec &s, ll mod)
{
auto inverse=[](ll a, ll m)
{
ll d,x,y;
exgcd(a,m,d,x,y);
return d==1?(x%m+m)%m:-1;
};
auto L=[](const vec &a, const vec &b)
{
int da=(a.size()>1||(a.size()==1&&a[0]))?a.size()-1:-1000;
int db=(b.size()>1||(b.size()==1&&b[0]))?b.size()-1:-1000;
return std::max(da,db+1);
};
auto prime_power = [&](const vec &s, ll mod, ll p, ll e)
{
// linear feedback shift register mod p^e, p is prime
std::vector<vec> a(e),b(e),an(e),bn(e),ao(e),bo(e);
vec t(e),u(e),r(e),to(e,1),uo(e),pw(e + 1);
pw[0]=1;
for(int i=pw[0]=1;i<=e;++i) pw[i]=pw[i-1]*p;
for(ll i=0;i<e;++i)
{
a[i]={pw[i]},an[i]={pw[i]};
b[i]={0},bn[i]={s[0]*pw[i]%mod};
t[i]=s[0]*pw[i]%mod;
if (t[i]==0)
{
t[i]=1,u[i]=e;
}
else
{
for(u[i]=0;t[i]%p==0;t[i]/=p,++u[i]);
}
}
for(size_t k=1;k<s.size();++k)
{
for(int g=0;g<e;++g)
{
if (L(an[g],bn[g])>L(a[g], b[g]))
{
ao[g]=a[e-1-u[g]];
bo[g]=b[e-1-u[g]];
to[g]=t[e-1-u[g]];
uo[g]=u[e-1-u[g]];
r[g]=k-1;
}
}
a=an,b=bn;
for(int o=0;o<e;++o)
{
ll d=0;
for(size_t i=0;i<a[o].size()&&i<=k;++i)
{
d=(d+a[o][i]*s[k-i])% mod;
}
if(d==0)
{
t[o]=1,u[o]=e;
}
else
{
for(u[o]=0,t[o]=d;t[o]%p==0;t[o]/=p,++u[o]);
int g=e-1-u[o];
if(L(a[g],b[g])==0)
{
extand(bn[o],k+1);
bn[o][k]=(bn[o][k]+d)%mod;
}
else
{
ll coef=t[o]*inverse(to[g],mod)%mod*pw[u[o]-uo[g]]%mod;
int m=k-r[g];
extand(an[o],ao[g].size()+m);
extand(bn[o],bo[g].size()+m);
for(size_t i=0;i<ao[g].size();++i)
{
an[o][i+m]-=coef*ao[g][i]%mod;
if(an[o][i+m]<0) an[o][i+m]+=mod;
}
while(an[o].size()&&an[o].back()==0) an[o].pop_back();
for(size_t i=0;i<bo[g].size();++i)
{
bn[o][i+m]-=coef*bo[g][i]%mod;
if(bn[o][i + m]<0) bn[o][i+m]-=mod;
}
while(bn[o].size()&&bn[o].back()==0) bn[o].pop_back();
}
}
}
}
return std::make_pair(an[0],bn[0]);
};
std::vector<std::tuple<ll,ll,int> >fac;
for(ll i=2;i*i<=mod;++i)
if(mod%i==0)
{
ll cnt=0,pw=1;
while(mod%i==0) mod/=i,++cnt,pw*=i;
fac.emplace_back(pw,i,cnt);
}
if(mod>1) fac.emplace_back(mod,mod,1);
std::vector<vec> as;
size_t n=0;
for (auto &&x:fac)
{
ll mod,p,e;
vec a,b;
std::tie(mod,p,e)=x;
auto ss=s;
for(auto &&x:ss) x%=mod;
std::tie(a,b)=prime_power(ss,mod,p,e);
as.emplace_back(a);
n=std::max(n,a.size());
}
vec a(n),c(as.size()),m(as.size());
for(size_t i=0;i<n;++i)
{
for(size_t j=0;j<as.size();++j)
{
m[j]=std::get<0>(fac[j]);
c[j]=i<as[j].size()?as[j][i]:0;
}
a[i]=crt(c,m);
}
return a;
}
ll gao(VI a,ll n,ll mod,bool prime=true)
{
VI c;
if(prime) c=BM(a);
else c=ReedsSloane(a,mod);
c.erase(c.begin());
for(int i=0;i<SZ(c);++i) c[i]=(mod-c[i])%mod;
return solve(n,c,VI(a.begin(),a.begin()+SZ(c)));
}
};
int main()
{
ll n, m;
scanf("%lld%lld",&n,&m);
vector<ll>f;
f.pb(0),f.pb(1);
for(int i=2;i<=2000;i++) f.pb((f[i-1]+f[i-2])%mod);
for(int i=1;i<=2000;i++) f[i]=linear_seq::powmod(f[i],m);
for(int i=1;i<=2000;i++) f[i]=(f[i-1]+f[i])%mod;
printf("%lld\n",linear_seq::gao(f,n,mod,false));//false表示mod为非质数。
return 0;
}
(2)模数为质数:
牛客: 斐波那契和
注意:从第1项开始。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<bitset>
#define ll long long
#define llu unsigned ll
#define pr make_pair
#define pb push_back
//#define lc (cnt<<1)
//#define rc (cnt<<1|1)
using namespace std;
const int inf=0x3f3f3f3f;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const double dnf=1e15;
const int mod=998244353;
const double eps=1e-8;
const int maxn=550;
namespace linear_seq
{
#define SZ(x) ((ll)(x).size())
#define FOR(i,a,b) for(int i(a);i<=(b);++i)
#define FOL(i,a,b) for(int i(a);i>=(b);--i)
typedef vector<ll> VI;
using vec = std::vector<ll>;
const int N=10010;
ll res[N],base[N],c[N],md[N];
const ll mod = ::mod;
vector<int> Md;
ll powmod(ll a,ll b)
{
ll res=1LL;
while(b)
{
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
void mul(ll *a,ll *b,int k)
{
for(int i=0;i<k+k;++i) c[i]=0;
for(int i=0;i<k;++i)
if(a[i])for(int j=0;j<k ;++j)
c[i+j]=(c[i+j]+a[i]*b[j])%mod;
for (int i=k+k-1;i>=k;i--)
if(c[i])for(int j=0;j<(int)Md.size();++ j)
c[i-k+Md[j]]=(c[i-k+Md[j]]-c[i]*md[Md[j]])%mod;
for(int i=0;i<k;++i) a[i]=c[i];
}
int solve(ll n,VI a,VI b)
{ // a 系数 b 初值 b[n+1]=a[0]*b[n]+...
ll ans=0,pnt=0;
int k=SZ(a);
for(int i=0;i<k;++i) md[k-1-i]=-a[i];
md[k]=1;Md.clear();
for(int i=0;i<k;++i) if(md[i]!=0)Md.push_back(i);
for(int i=0;i<k;++i) res[i]=base[i]=0;
res[0]=1;
while ((1ll<<pnt)<=n) pnt++;
for (int p=pnt;p>=0;p--)
{
mul(res,res,k);
if ((n>>p)&1)
{
for (int i=k-1;i>=0;i--) res[i+1]=res[i];
res[0]=0;
for(int j=0;j<(int)Md.size();++j)
res[Md[j]]=(res[Md[j]]-res[k]*md[Md[j]])%mod;
}
}
for(int i=0;i<k;i++) ans=(ans+res[i]*b[i])%mod;
if (ans<0) ans+=mod;
return ans;
}
VI BM(VI s)
{
VI C(1,1),B(1,1);
int L=0,m=1,b=1;
for(int n=0;n<(int)s.size();++n)
{
ll d=0;
for(int i=0;i<L+1;++ i) d=(d+(ll)C[i]*s[n-i])%mod;
if(d==0) ++m;
else if(2*L<=n)
{
VI T=C;
ll c=mod-d*powmod(b,mod-2)%mod;
while (SZ(C)<SZ(B)+m)C.push_back(0);
for(int i=0;i<(int)B.size();++i) C[i+m]=(C[i+m]+c*B[i])%mod;
L=n+1-L; B=T; b=d; m=1;
}
else
{
ll c=mod-d*powmod(b,mod-2)%mod;
while (SZ(C)<SZ(B)+m)C.push_back(0);
for(int i=0;i<(int)B.size();++ i) C[i+m]=(C[i+m]+c*B[i])%mod;
++m;
}
}
return C;
}
static void extand(vec &a, size_t d, ll value=0)
{
if (d<=a.size()) return;
a.resize(d, value);
}
static void exgcd(ll a, ll b, ll &g, ll &x, ll &y)
{
if (!b) x=1,y=0,g=a;
else
{
exgcd(b,a%b,g,y,x);
y-=x*(a/b);
}
}
static ll crt(const vec &c, const vec &m)
{
int n=c.size();
ll M=1,ans=0;
for(int i=0;i<n;++i) M*=m[i];
for(int i=0;i<n;++i)
{
ll x,y,g,tm=M/m[i];
exgcd(tm,m[i],g,x,y);
ans=(ans+tm*x*c[i]%M)%M;
}
return (ans+M)%M;
}
static vec ReedsSloane(const vec &s, ll mod)
{
auto inverse=[](ll a, ll m)
{
ll d,x,y;
exgcd(a,m,d,x,y);
return d==1?(x%m+m)%m:-1;
};
auto L=[](const vec &a, const vec &b)
{
int da=(a.size()>1||(a.size()==1&&a[0]))?a.size()-1:-1000;
int db=(b.size()>1||(b.size()==1&&b[0]))?b.size()-1:-1000;
return std::max(da,db+1);
};
auto prime_power = [&](const vec &s, ll mod, ll p, ll e)
{
// linear feedback shift register mod p^e, p is prime
std::vector<vec> a(e),b(e),an(e),bn(e),ao(e),bo(e);
vec t(e),u(e),r(e),to(e,1),uo(e),pw(e + 1);
pw[0]=1;
for(int i=pw[0]=1;i<=e;++i) pw[i]=pw[i-1]*p;
for(ll i=0;i<e;++i)
{
a[i]={pw[i]},an[i]={pw[i]};
b[i]={0},bn[i]={s[0]*pw[i]%mod};
t[i]=s[0]*pw[i]%mod;
if (t[i]==0)
{
t[i]=1,u[i]=e;
}
else
{
for(u[i]=0;t[i]%p==0;t[i]/=p,++u[i]);
}
}
for(size_t k=1;k<s.size();++k)
{
for(int g=0;g<e;++g)
{
if (L(an[g],bn[g])>L(a[g], b[g]))
{
ao[g]=a[e-1-u[g]];
bo[g]=b[e-1-u[g]];
to[g]=t[e-1-u[g]];
uo[g]=u[e-1-u[g]];
r[g]=k-1;
}
}
a=an,b=bn;
for(int o=0;o<e;++o)
{
ll d=0;
for(size_t i=0;i<a[o].size()&&i<=k;++i)
{
d=(d+a[o][i]*s[k-i])% mod;
}
if(d==0)
{
t[o]=1,u[o]=e;
}
else
{
for(u[o]=0,t[o]=d;t[o]%p==0;t[o]/=p,++u[o]);
int g=e-1-u[o];
if(L(a[g],b[g])==0)
{
extand(bn[o],k+1);
bn[o][k]=(bn[o][k]+d)%mod;
}
else
{
ll coef=t[o]*inverse(to[g],mod)%mod*pw[u[o]-uo[g]]%mod;
int m=k-r[g];
extand(an[o],ao[g].size()+m);
extand(bn[o],bo[g].size()+m);
for(size_t i=0;i<ao[g].size();++i)
{
an[o][i+m]-=coef*ao[g][i]%mod;
if(an[o][i+m]<0) an[o][i+m]+=mod;
}
while(an[o].size()&&an[o].back()==0) an[o].pop_back();
for(size_t i=0;i<bo[g].size();++i)
{
bn[o][i+m]-=coef*bo[g][i]%mod;
if(bn[o][i + m]<0) bn[o][i+m]-=mod;
}
while(bn[o].size()&&bn[o].back()==0) bn[o].pop_back();
}
}
}
}
return std::make_pair(an[0],bn[0]);
};
std::vector<std::tuple<ll,ll,int> >fac;
for(ll i=2;i*i<=mod;++i)
if(mod%i==0)
{
ll cnt=0,pw=1;
while(mod%i==0) mod/=i,++cnt,pw*=i;
fac.emplace_back(pw,i,cnt);
}
if(mod>1) fac.emplace_back(mod,mod,1);
std::vector<vec> as;
size_t n=0;
for (auto &&x:fac)
{
ll mod,p,e;
vec a,b;
std::tie(mod,p,e)=x;
auto ss=s;
for(auto &&x:ss) x%=mod;
std::tie(a,b)=prime_power(ss,mod,p,e);
as.emplace_back(a);
n=std::max(n,a.size());
}
vec a(n),c(as.size()),m(as.size());
for(size_t i=0;i<n;++i)
{
for(size_t j=0;j<as.size();++j)
{
m[j]=std::get<0>(fac[j]);
c[j]=i<as[j].size()?as[j][i]:0;
}
a[i]=crt(c,m);
}
return a;
}
ll gao(VI a,ll n,ll mod,bool prime=true)
{
VI c;
if(prime) c=BM(a);
else c=ReedsSloane(a,mod);
c.erase(c.begin());
for(int i=0;i<SZ(c);++i) c[i]=(mod-c[i])%mod;
return solve(n,c,VI(a.begin(),a.begin()+SZ(c)));
}
};
ll f[maxn];
ll mypow(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b&1) ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
int main()
{
ll n,k;
scanf("%lld%lld",&n,&k);
f[1]=f[2]=1;
for(int i=3;i<maxn;i++)
f[i]=(f[i-1]+f[i-2])%mod;
ll ans=0;
vector<ll>vc;
for(int i=1;i<=500;i++)
{
ans=(ans+mypow(i,k)*f[i])%mod;
vc.pb(ans);
}
//质数的时候false true均可
//因为false可以处理更一般的情况
//printf("%lld\n",linear_seq::gao(vc,n-1,mod,false));
printf("%lld\n",linear_seq::gao(vc,n-1,mod,true));
return 0;
}