Okabe and El Psy Kongroo

原题:Okabe and El Psy Kongroo

原题大意

从(0,0) 到(k,0),每个点可以到达右上,右,右下这三个点,但必须在c下方,0上方(包括0边界),问最终到达(k,0)有多少种方案。

算法分析

dp,因为ci是一条与x轴平行的线段,所以从ai到ai+1的每一次的贡献都是一样的,可以用矩阵加速,c最多为15,所以不会超时

程序代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
struct matrix{
  ll val[16][16];
  matrix(){memset(val,0,sizeof(val));}
  matrix operator*(const matrix & rhs)const{
    matrix ret;
    for(int i = 0; i < 16; i++)
      for(int j = 0; j < 16; j++)
        for(int k = 0; k < 16; k++)
          ret.val[i][j] += val[i][k] * rhs.val[k][j]%mod,
          ret.val[i][j] %= mod;
    return ret;
  }
};
matrix pow_mod(const matrix& b, ll p){
  matrix ret, cur = b;
  for(int i = 0; i < 16; i++)
    ret.val[i][i] = 1;
  while(p){
    if(p & 1)
      ret = ret * cur;
    cur = cur * cur;
    p>>=1;
  }
  return ret;
}
int n;
ll k;
int main(){
  ios::sync_with_stdio(false);
  cin.tie(0);cout.tie(0);
  cin >> n >> k;
  matrix ans;
  ans.val[0][0] = 1;
  for(int i = 1; i <= n; i++){
    ll a, b;
    int c;
    cin >> a >> b >> c;
    matrix mul;
    for(int j = 0; j <= c; j++)
      for(int l = j-1; l <= j+1; l++)
        if(l >= 0 && l <= c)
          mul.val[j][l] = 1;
    ans = pow_mod(mul, min(b,k) - a) * ans;
  }
  cout << ans.val[0][0] << endl;
  return 0;
}