比較好的一道題,首先是是遞推,遞推很容易想到,我們假設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;
}