#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define VV(a, b, c, d) vector>(a, vector(b, c)) #define VVV(a, b, c, d, e) vector>>(a, VV(b, c, d, e)); #define all(obj) (obj).begin(), (obj).end() typedef long long int ll; typedef long double ld; typedef std::vector v1; typedef std::vector v2; typedef std::vector v3; using namespace std; template struct StaticModMatrix{ private: using matrix = StaticModMatrix; using vec = vector; using mat = vector; static constexpr uint64_t init_neg(){ uint64_t NEG = 0, s = 1, t = 0; for(int i=0;i<64;i++){ if(~t & 1){ t += MOD; NEG += s; } t >>= 1; s <<= 1; } return NEG; } static constexpr uint64_t init_r2(){ uint64_t r2 = ((uint64_t)1<<32) % MOD; return r2 * r2 % MOD; } static constexpr uint64_t NEG_INV = init_neg(); static constexpr uint64_t R2 = init_r2(); static inline uint64_t generate(uint64_t x){ return reduce(x * R2); } static inline uint64_t reduce(uint64_t x){ x = (x + ((uint32_t)x * (uint32_t)NEG_INV) * MOD) >> 32; return x < MOD? x: x-MOD; } // (n, k) * (k, m) -> (n * m) // モンゴメリ乗算を使うと剰余演算を行う回数がN^3->N^2にできる // 乗算がボトルネックになりがちだけど定数倍が早いかわかんない static mat mul_mat(mat vl, mat vr){ int N = vl.size(), K = vl[0].size(), M = vr[0].size(); mat ret(N, vec(K, 0)); for(int i=0;i (n, m) static mat add_mat(const mat &vl, const mat &vr){ int N = vl.size(), M = vl[0].size(); mat ret = vl; for(int i=0;i=MOD) ret[i][j] -= MOD; } } return ret; } // (n, m) - (n, m) -> (n, m) static mat sub_mat(const mat &vl, const mat &vr){ int N = vl.size(), M = vl[0].size(); mat ret = vl; for(int i=0;i=MOD) ret[i][j] -= MOD; } } return ret; } static mat mul_ll(const mat &vl, const ll vr){ int N = vl.size(), M = vl[0].size(); mat ret = vl; uint64_t x = generate(vr); for(int i=0;i (n, n) k>=2の場合正方行列じゃないと壊れる static mat pow_mat(const mat &vl, ll k){ assert(vl.size()==vl[0].size()); int N = vl.size(); mat ret = eye(N), MUL = vl; while(k){ if(k&1) ret = mul_mat(ret, MUL); k >>= 1; MUL = mul_mat(MUL, MUL); } return ret; } mat val; public: int n, m; StaticModMatrix(){} StaticModMatrix(int n, int m, int x):val(n, vec(m, generate(x))), n(n), m(m){} StaticModMatrix(const mat &v):val(v), n(v.size()), m(v[0].size()){} StaticModMatrix(const vector> &v): val(v.size(), vec(v[0].size())), n(v.size()), m(v[0].size()){ for(int i=0;ival, vr.val));} matrix operator - (const matrix &vr){return matrix(sub_mat(this->val, vr.val));} matrix operator * (const matrix &vr){return matrix(mul_mat(this->val, vr.val));} matrix operator ^ (const ll vr){return matrix(pow_mat(this->val, vr));} matrix operator * (const ll vr){return matrix(mul_ll(this->val, vr));} matrix operator += (const matrix &vr){return (*this) = matrix(add_mat(this->val, vr.val));} matrix operator -= (const matrix &vr){return (*this) = matrix(sub_mat(this->val, vr.val));} matrix operator *= (const matrix &vr){return (*this) = matrix(mul_mat(this->val, vr.val));} matrix operator ^= (const ll vr){return (*this) = matrix(pow_mat(this->val, vr));} matrix operator *= (const ll vr){return (*this) = matrix(mul_ll(this->val, vr));} vec& operator [] (const int i){return val[i];} }; int main(){ ll m, k;scanf("%lld %lld", &m,&k); using mat = StaticModMatrix<1000000007>; mat a(m, m, 0); for(int i=0;i=m?i+j-m:i+j)]++; a[i][(i*j)%m]++; } } a ^= k; printf("%lld\n", a[0][0]); }