#define _USE_MATH_DEFINES #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; #define IOS ios::sync_with_stdio(false); cin.tie(0); #define FOR(i, s, n) for(int i = (s), i##_len=(n); i < i##_len; ++i) #define FORS(i, s, n) for(int i = (s), i##_len=(n); i <= i##_len; ++i) #define VFOR(i, s, n) for(int i = (s); i < (n); ++i) #define VFORS(i, s, n) for(int i = (s); i <= (n); ++i) #define REP(i, n) FOR(i, 0, n) #define REPS(i, n) FORS(i, 0, n) #define VREP(i, n) VFOR(i, 0, n) #define VREPS(i, n) VFORS(i, 0, n) #define RFOR(i, s, n) for(int i = (s), i##_len=(n); i >= i##_len; --i) #define RFORS(i, s, n) for(int i = (s), i##_len=(n); i > i##_len; --i) #define RREP(i, n) RFOR(i, n, 0) #define RREPS(i, n) RFORS(i, n, 0) #define ALL(v) (v).begin(), (v).end() #define SORT(v) sort(ALL(v)) #define RSORT(v) sort(ALL(v), greater()) #define SZ(x) ((int)(x).size()) #define PB push_back #define EB emplace_back #define MP make_pair #define MT make_tuple #define BIT(n) (1LL<<(n)) #define UNIQUE(v) v.erase(unique(ALL(v)), v.end()) using ll = long long; using ull = unsigned long long; using Pi_i = pair; using VB = vector; using VC = vector; using VD = vector; using VI = vector; using VLL = vector; using VS = vector; using VSH = vector; using VULL = vector; const int MOD = 1000000007; const int INF = 1000000000; const int NIL = -1; template bool chmax(T &a, const S &b){ if(a < b){ a = b; return true; } return false; } template bool chmin(T &a, const S &b){ if(b < a){ a = b; return true; } return false; } template class Matrix{ private: vector> A; public: Matrix(){} Matrix(size_t m, size_t n): A(m, vector(n, 0)) {} Matrix(size_t n): A(n, vector(n, 0)) {} Matrix(size_t m, size_t n, T a): A(m, vector(n, a)) {} Matrix(const Matrix& mat){if(this != &mat) A = mat.A;} Matrix(const vector> &v){ size_t m = v.size(); assert(m != 0); size_t n = v[0].size(); REP(i, m) assert(v[i].size() == n); A = v; } Matrix(const vector &v){ size_t m = v.size(); assert(m != 0); A.resize(1); A[0] = v; } ~Matrix() {} size_t height() const{return A.size();} size_t width() const{ if(!height()) return 0; return A[0].size(); } void setHeight(int h){A.resize(h, vector(width(), 0));} void setWidth(int w){ size_t m = height(); REP(i, m) A[i].resize(w, 0); } void setSize(int h, int w){ setHeight(h); setWidth(w); } void inputNoChangeSize(){ size_t m = height(), n = width(); REP(i, m) REP(j, n) cin >> A[i][j]; } void input(int h, int w){ setSize(h, w); inputNoChangeSize(); } void input(){ int h, w; cin >> h >> w; input(h, w); } bool sameSize(const Matrix& mat) const{ return height() == mat.height() && width() == mat.width(); } inline const vector &operator[](int idx) const{return A.at(idx);} inline vector &operator[](int k){return (A.at(k));} void print2D(int w) const{ size_t m = height(), n = width(); REP(i, m){ REP(j, n){ if(j) cout << " "; cout << setw(w) << (*this)[i][j]; } cout << "\n"; } } void print2D() const{ size_t m = height(), n = width(); REP(i, m){ REP(j, n){ if(j) cout << " "; cout << (*this)[i][j]; } cout << "\n"; } } friend ostream& operator<<(ostream& os, const Matrix& B){ size_t m = B.height(), n = B.width(); REP(i, m){ REP(j, n){ if(j) os << " "; os << B[i][j]; } os << "\n"; } return (os); } static Matrix identity(size_t n){ Matrix ret(n); REP(i, n) ret[i][i] = 1; return ret; } Matrix transpose() const{ size_t n = height(), m = width(); Matrix ret(m, n); REP(i, m) REP(j, n) ret[i][j] = (*this)[j][i]; return ret; } Matrix operator+() const{return *this;} Matrix operator-() const{ size_t m = height(), n = width(); Matrix temp(height(), width()); REP(i, m) REP(j, n) temp[i][j] = -(*this)[i][j]; return temp; } Matrix& operator=(const Matrix& B){ if(this != &B){ A = B.A; } return *this; } Matrix& operator+=(const Matrix& B){ assert(sameSize(B)); size_t m = height(), n = width(); REP(i, m) REP(j, n) (*this)[i][j] += B[i][j]; return *this; } Matrix& operator-=(const Matrix& B){ assert(sameSize(B)); size_t m = height(), n = width(); REP(i, m) REP(j, n) (*this)[i][j] -= B[i][j]; return *this; } Matrix& operator*=(const Matrix& B){ size_t m = height(), n = width(), l = B.width(); assert(n == B.height()); vector> C(m, vector(l, 0)); REP(i, m) REP(j, l) REP(k, n) C[i][j] = (C[i][j] + (*this)[i][k] * B[k][j]); A.swap(C); return *this; } Matrix& operator*=(const T a){ size_t m = height(), n = width(); REP(i, m) REP(j, n) (*this)[i][j] *= a; return *this; } Matrix& operator%=(const ll &mod){ size_t m = height(), n = width(); REP(i, m) REP(j, n) (*this)[i][j] %= mod; return *this; } Matrix& operator^=(const Matrix &B){ assert(sameSize(B)); size_t m = height(), n = width(); REP(i, m) REP(j, n) (*this)[i][j] ^= B[i][j]; return *this; } Matrix& operator|=(const Matrix &B){ assert(sameSize(B)); size_t m = height(), n = width(); REP(i, m) REP(j, n) (*this)[i][j] |= B[i][j]; return *this; } Matrix& operator&=(const Matrix &B){ size_t m = height(), n = width(), l = B.width(); assert(n == B.height()); vector> C(m, vector(l, 0)); REP(i, m) REP(j, l) REP(k, n) C[i][j] = (C[i][j] ^ ((*this)[i][k] & B[k][j])); A.swap(C); return *this; } Matrix operator+(const Matrix& mat) const{ Matrix temp(*this); return temp += mat; } Matrix operator-(const Matrix& mat) const{ Matrix temp(*this); return temp -= mat; } Matrix operator*(const Matrix& mat) const{ Matrix temp(*this); return temp *= mat; } Matrix operator*(const T& a) const{ Matrix temp(*this); return temp *= a; } friend Matrix operator*(T a, const Matrix& B){ return B * a; } Matrix operator%(const ll mod) const{ Matrix temp(*this); return temp %= mod; } Matrix operator^(const Matrix& mat) const{ Matrix temp(*this); return temp ^= mat; } Matrix operator|(const Matrix& mat) const{ Matrix temp(*this); return temp |= mat; } Matrix operator&(const Matrix& mat) const{ Matrix temp(*this); return temp &= mat; } bool operator==(const Matrix& mat) const{ if(!sameSize(mat)) return false; size_t m = height(), n = width(); REP(i, m) REP(j, n) if((*this)[i][j] != mat[i][j]) return false; return true; } bool operator!=(const Matrix& mat) const{return !(*this == mat);} Matrix powWithoutMod(ll b) const{ size_t n = height(); assert(n == width()); Matrix ret = identity(n); Matrix a = *this; while(b){ if(b & 1) ret = ret * a; a = a * a; b /= 2; } return ret; } Matrix power(ll b, ll mod) const{ size_t n = height(); assert(n == width()); Matrix ret = identity(n); Matrix a = *this; while(b){ if(b & 1) ret = (ret * a) % mod; a = (a * a) % mod; b /= 2; } return ret; } Matrix power(ll b) const{ return power(b, MOD); } Matrix powXorAnd(ll b) const{ size_t n = height(); assert(n == width()); Matrix ret = identity(n); ret *= -1; Matrix a = *this; while(b){ if(b & 1) ret = ret & a; a = a & a; b /= 2; } return ret; } }; int main(){ int N, M; cin >> N >> M; Matrix A(2); A[0][0] = A[0][1] = A[1][0] = 1; A = A.power(N-2, M); cout << A[0][0] << endl; return 0; }