题目:http://codeforces.com/contest/821/problem/E
递推方程很容易看出来,dp【i】【j】表示到达( i , j )这个点的路径条数
dp【i】【j】=dp【i-1】【j+1】+dp【i-1】【j】+dp【i-1】【j-1】
但k太大,肯定不能直接递推,快速幂优化一下,y的坐标范围是0~15,所以矩阵长度16就够了,至于c的限制,把转移矩阵的一些位置赋零就可以了,忘记考虑了一种情况,错了很多发。。。。
2 2
0 1 1
1 2 0
结果应该是1
因为不能直接从(1,1)点到(2,0)
#include<bits/stdc++.h>
using namespace std;
struct node
{
long long a[16][16];
}one,dp;
const int mo=1e9+7;
node mult(node a,node b)
{
int i,j,k;
node c;
memset(c.a,0,sizeof(c.a));
for(i=0;i<16;i++)
{
for(j=0;j<16;j++)
{
for(k=0;k<16;k++)
{
c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%mo;
}
}
}
return c;
}
node pow(node a,long long w)
{
node ans;
memset(ans.a,0,sizeof(ans.a));
for(int i=0;i<16;i++)
ans.a[i][i]=1;
while(w)
{
if(w&1)
{
ans=mult(ans,a);
}
a=mult(a,a);
w>>=1;
}
return ans;
}
int main()
{
int i,j,tempc;
long long n,k,tempa,tempb;
for(i=0;i<16;i++)
{
for(j=max(0,i-1);j<=min(15,i+1);j++)
one.a[j][i]=1;
}
cin>>n>>k;
dp.a[0][0]=1;
while(n--)
{
scanf("%I64d %I64d %d",&tempa,&tempb,&tempc);
node temp=one;
temp.a[tempc+1][tempc]=0;
for(i=tempc+1;i<16;i++)
{
for(j=0;j<16;j++)
temp.a[j][i]=0;
}
dp=mult(dp,pow(temp,min(tempb,k)-tempa));
}
cout<<dp.a[0][0]<<endl;
return 0;
}