比较好的一道题,首先是是递推,递推很容易想到,我们假设dp[i][j]表示走到i,j的方案数 那么其实就是求出每一段a[i]-b[i]的值 就可以得出来了
可以得到
dp[i][j+1] += dp[i-1][j]; j+1<=ci
dp[i][j-1] += dp[i-1][j]; j-1>=0
dp[i][j] += dp[i-1][j];
因为i的范围很大,看了解法后知道要用矩阵快速幂
我们构造一个16*16的矩阵 矩阵mat[i][j] 表示从y轴的i点走到y轴的j点的方案数,当长度为一的时候这个矩阵很好构造 那么长度为2的时候其实就是mat^2,那么直接快速幂求出长度为b[i]-a[i],然后每一段的方案知道后这个题就基本解决了 详细看代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<string>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cstring>
using namespace std;
#define LL long long
#define N 18
#define MOD 1000000007ll
struct Matrix{
LL dat[N][N];
int n;
Matrix(){
_init();
}
void _init(){
memset(dat,0,sizeof(dat));
}
LL* const operator[](int i)
{
return dat[i];
}
const LL* operator[](int i)const
{
return dat[i];
}
void operator%(LL mod)
{
for(int i = 0;i<n;i++)
{
for(int j = 0;j<n;j++)
{
dat[i][j]%=mod;
}
}
}
Matrix operator *(const Matrix& mat){
Matrix temp;
temp.n = mat.n;
for(int i = 0;i<n;i++)
{
for(int j = 0;j<n;j++)
{
for(int k = 0;k<n;k++)
{
temp[i][j] += dat[i][k]*mat[k][j];
temp[i][j]%=1000000007ll;
}
}
}
return temp;
}
};
Matrix ans,sta;
void quickPow(LL len)
{
while(len)
{
if(len&1)
{
ans = ans*sta;
ans%MOD;
}
len >>= 1;
sta = sta*sta;
sta%MOD;
}
}
int main()
{
LL n,k;
while(scanf("%lld%lld",&n,&k)!=EOF)
{
LL a[105],b[105],c[105];
for(int i = 0;i<n;i++)
{
scanf("%lld%lld%lld",&a[i],&b[i],&c[i]);
}
ans._init();
ans.n = 16;
sta.n = 16;
for(int i = 0;i<=ans.n;i++)
{
ans[i][i] = 1;
}
sta._init();
for(int i = 0;i<n;i++)
{
sta._init();
for(int j = 0;j<=c[i];j++)
{
if(j+1<=c[i])
sta[j][j+1]++;
if(j-1>=0)
sta[j][j-1]++;
sta[j][j]++;
}
if(b[i]>k)
{
quickPow(k-a[i]);
}
else quickPow(b[i]-a[i]);
}
printf("%lld\n",ans[0][0]);
}
return 0;
}