ProjectEuler237 Tours on a 4 x n playing board


思路是这样的
插头dp-->打表-->OEIS查表-->通项公式-->矩阵快速幂优化线性递推
OEIS竟然有这个东西的生成函数啊
答案为15836928
这是最终代码

#include 

using namespace std;

#define MOD 191981
#define mod 100000000
#define ll long long

struct Matrix {
  vector > a;
  int n, m;
  void init(int n, int m) {
    this->n = n, this->m = m;
    a.resize(n);
    for(int i = 0; i < n; ++i) a[i].resize(m);
  }
  vector& operator [](int index_x) {
    return a[index_x];
  }
  friend Matrix operator * (Matrix lhs, Matrix rhs) {
    Matrix c;
    c.init(lhs.n, rhs.m);
    for(int i = 0; i < lhs.n; ++i)
      for(int j = 0; j < rhs.m; ++j)
        for(int k = 0; k < lhs.m; ++k)
          c[i][j] = (c[i][j]+1LL*lhs[i][k]*rhs[k][j]%mod)%mod;
    return c;
  }
};

Matrix eye(int n) {
  Matrix c;
  c.init(n, n);
  for(int i = 0; i < n; ++i)
    c[i][i] = 1;
  return c;
}

Matrix fpow(Matrix x, ll p) {
  Matrix ret = eye(x.n);
  while(p) {
    if(p&1) ret = ret*x;
    x = x*x;
    p >>= 1;
  }
  return ret;
}

//a(n) = 2*a(n-1) + 2*a(n-2) - 2*a(n-3) + a(n-4)

int main() {
  ll n;
  scanf("%lld", &n);
  if(n == 1) printf("1\n");
  else if(n == 2) printf("1\n");
  else if(n == 3) printf("4\n");
  else if(n == 4) printf("8\n");
  else {
    Matrix m0, p, ans;
    m0.init(4, 1);
    m0[0][0] = 8, m0[1][0] = 4, m0[2][0] = 1, m0[3][0] = 1;
    p.init(4, 4);
    p[0][0] = 2, p[0][1] = 2, p[0][2] = -2, p[0][3] = p[1][0] = p[2][1] = p[3][2] = 1;
    ans = fpow(p, n-4)*m0;
    printf("%d\n", ans[0][0]);
  }
  return 0;
}

相关