#include "bits/stdc++.h" using namespace std; #define REP(i, n) for(ll i = 0;i < n;i++) #define ll long long #define MOD 1000000007 ll n,m; class modint { public: long long value; //+ const modint operator + (modint mtmp) const{ modint mdnt; mdnt.value=(this->value+mtmp.value); if (mdnt.value>=MOD)mdnt.value-=MOD; return mdnt; } const modint operator + (long long ltmp) const{ modint mdnt; long long tmp=ltmp%MOD; if (tmp<0)tmp+=MOD; mdnt.value=(this->value+tmp); if (mdnt.value>=MOD)mdnt.value-=MOD; return mdnt; } //- const modint operator - (modint mtmp) const{ modint mdnt; mdnt.value=(this->value-mtmp.value+MOD); if (mdnt.value>=MOD)mdnt.value-=MOD; return mdnt; } const modint operator - (long long ltmp) const{ modint mdnt; long long tmp=ltmp%MOD; if (tmp<0)tmp+=MOD; mdnt.value=(this->value-tmp+MOD); if (mdnt.value>=MOD)mdnt.value-=MOD; return mdnt; } //* const modint operator * (modint mtmp) const{ modint mdnt; mdnt.value=(this->value*mtmp.value)%MOD; return mdnt; } const modint operator * (long long ltmp) const{ modint mdnt; long long ltmpm=ltmp%MOD; if (ltmpm<0)ltmpm+=MOD; mdnt.value=(this->value*ltmpm)%MOD; return mdnt; } /// const modint operator / (long long ltmp) const{ modint mdnt; long long ltmpm=ltmp%MOD; if (ltmpm<0)ltmpm+=MOD; long long mdnv=this->value; long long x0=MOD,x1=ltmpm,x2,n0=0LL,n1=1LL,n2,t=mdnv%ltmpm,m,ans; if (t==0){ mdnt.value=mdnv/ltmpm; return mdnt; } for(int i=0;i<900;i++){ m=x0/x1; x2=x0-x1*m; n2=(n0-m*n1)%MOD; if (x2==1){ ans=(n2+MOD)%MOD; break; } x0=x1;x1=x2; n0=n1;n1=n2; } mdnt.value=(mdnv+((t*ans)%MOD)*ltmpm-t)/ltmpm; return mdnt; } const modint operator / (modint mtmp) const{ return (*this)/mtmp.value; } //% const modint operator % (long long ltmp) const{ modint mdnt; mdnt.value=(this->value%ltmp); return mdnt; } //代入演算子のオーバーロード modint &operator = (const modint mtmp) { this->value = mtmp.value; return *this; } modint &operator = (const long long ltmp) { this->value = ltmp%MOD; if ((this->value)<0)this->value+=MOD; return *this; } //+= modint &operator += (const modint mtmp) { this->value = (this->value+mtmp.value); if (this->value>=MOD)this->value-=MOD; return *this; } modint &operator += (long long ltmp) { long long tmp=ltmp%MOD; if (tmp<0)tmp+=MOD; this->value=(this->value+tmp); if (this->value>=MOD)this->value-=MOD; return *this; } //-= modint &operator -= (const modint mtmp) { this->value = (this->value-mtmp.value+MOD); if (this->value>=MOD)this->value-=MOD; return *this; } modint &operator -= (long long ltmp) { long long tmp=ltmp%MOD; if (tmp<0)tmp+=MOD; this->value=(this->value-tmp+MOD); if (this->value>=MOD)this->value-=MOD; return *this; } //*= modint &operator *= (const modint mtmp) { this->value = this->value*mtmp.value%MOD; return *this; } modint &operator *= (long long ltmp) { this->value = this->value*(ltmp%MOD)%MOD; if (this->value<0)this->value+=MOD; return *this; } ///= modint &operator /= (const modint mtmp) { modint tmp=(*this)/mtmp.value; this->value = tmp.value; return *this; } modint &operator /= (long long ltmp) { modint tmp=(*this)/ltmp; this->value = tmp.value; return *this; } //%= modint &operator %= (long long ltmp) { this->value%=ltmp; return *this; } //exp関数 //aのn乗 mod c modint exp(long long n){ long long ans=1LL,aa=this->value,beki=n; for(int i=0;i<64;i++){ if (beki%2==1) ans=ans*aa%MOD; aa=aa*aa%MOD; beki/=2; if (beki==0)break; } modint mdnt; mdnt.value=ans; return mdnt; } //friend ostream& operator << (ostream& os, const modint& m); }; ostream& operator << (ostream& os, const modint& m) { os << m.value; return os; } using vi = vector; // intの1次元の型に vi という別名をつける using vvi = vector; // intの2次元の型に vvi という別名をつける //行列累乗 void matmul(vvi &C,vvi A,vvi B) { int lpnm=A.size(); REP(i,lpnm){ REP(j,lpnm){ C[i][j]=0; REP(l,lpnm){ C[i][j]=C[i][j]+A[l][j]*B[i][l]; } } } } void matpow(vvi &matans,vvi &imat,ll num){ int lpnm=imat.size(); vvi updmat(lpnm, vi(lpnm)); // k * k の正方行列 REP(i,lpnm) matans[i][i]=1;//単位行列 I REP(i,lpnm)REP(j,lpnm)updmat[i][j]=imat[i][j]; while(num) { if (num%2==1) { matmul(matans,matans,updmat); } num/=2; matmul(updmat,updmat,updmat); } return; } int main(){ cin >> n >> m; int k=2; vvi mat2d(k, vi(k)); // k * k の正方行列 mat2d[0][0]=1; mat2d[1][0]=1; mat2d[0][1]=1; vvi ansmat(k, vi(k)); // k * k の正方行列 matpow(ansmat,mat2d,m-1); modint a,b; a=ansmat[0][0]; b=ansmat[0][1]; ansmat[0][1]=ansmat[1][0]=0; matpow(ansmat,mat2d,m); vvi mat2d2(k+1, vi(k+1)); // k * k の正方行列 REP(i,2){ REP(j,2){ mat2d2[i][j]=ansmat[i][j]; } } mat2d2[2][2]=1; mat2d2[0][2]=1; vvi ansmat2(k+1, vi(k+1)); // k * k の正方行列 matpow(ansmat2,mat2d2,n); cout<