You are running through a rectangular field. This field can be represented as a matrix with 3 rows and m columns. (i, j) denotes a cell belonging to i-th row and j-th column.
You start in (2, 1) and have to end your path in (2, m). From the cell (i, j) you may advance to:
- (i - 1, j + 1) — only if i > 1,
- (i, j + 1), or
- (i + 1, j + 1) — only if i < 3.
However, there are n obstacles blocking your path. k-th obstacle is denoted by three integers ak, lk and rk, and it forbids entering any cell (ak, j) such that lk ≤ j ≤ rk.
You have to calculate the number of different paths from (2, 1) to (2, m), and print it modulo 109 + 7.
The first line contains two integers n and m (1 ≤ n ≤ 104, 3 ≤ m ≤ 1018) — the number of obstacles and the number of columns in the matrix, respectively.
Then n lines follow, each containing three integers ak, lk and rk (1 ≤ ak ≤ 3, 2 ≤ lk ≤ rk ≤ m - 1) denoting an obstacle blocking every cell (ak, j) such that lk ≤ j ≤ rk. Some cells may be blocked by multiple obstacles.
Print the number of different paths from (2, 1) to (2, m), taken modulo 109 + 7. If it is impossible to get from (2, 1) to (2, m), then the number of paths is 0.
2 5 1 3 4 2 2 3
2
#include<bits/stdc++.h>
using namespace std;
const int MAX=1e6;
const int MOD=1e9+7;
const double PI=acos(-1);
typedef __int64 ll;
int sum[4];
ll a[3];//分别储存每行的方案数
struct data{ll b[3][3];};
struct lenka
{
ll x,y,in;
}A[MAX];
int cmp(const lenka& p,const lenka& q){return p.y<q.y;}//对端点排序
data cla(const data& p,const data& q)
{
data c;
memset(c.b,0,sizeof c.b);
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
for(int k=0;k<3;k++)
{
c.b[i][j]+=p.b[i][k]*q.b[k][j]%MOD;
c.b[i][j]%=MOD;
}
}
}
return c;
}
void POW(ll n)
{
data res,b;
memset(res.b,0,sizeof res.b);
memset(b.b,0,sizeof b.b);
for(int i=0;i<3;i++)res.b[i][i]=1;
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)b.b[i][j]=(sum[j]==0);//根据当前行是否有障碍来确定友矩阵
}
b.b[0][2]=b.b[2][0]=0;
while(n)
{
if(n&1)res=cla(b,res);
b=cla(b,b);
n/=2;
}
ll x=(a[0]*res.b[0][0]%MOD+a[1]*res.b[1][0]%MOD+a[2]*res.b[2][0]%MOD)%MOD;
ll y=(a[0]*res.b[0][1]%MOD+a[1]*res.b[1][1]%MOD+a[2]*res.b[2][1]%MOD)%MOD;
ll z=(a[0]*res.b[0][2]%MOD+a[1]*res.b[1][2]%MOD+a[2]*res.b[2][2]%MOD)%MOD;
a[0]=x;
a[1]=y;
a[2]=z;//更新方案数
}
int main()
{
ll n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
ll x,L,R;
scanf("%I64d%I64d%I64d",&x,&L,&R);
A[i].x=x-1;
A[i].y=L-1;
A[i].in=1;
A[i+n].x=x-1;
A[i+n].y=R;
A[i+n].in=-1;
}
sort(A+1,A+2*n+1,cmp);
memset(sum,0,sizeof sum);
memset(a,0,sizeof a);
a[1]=1;
ll L=1;//记录一次更新到的位置
for(int i=1;i<=2*n;i++)
{
POW(A[i].y-L);
L=A[i].y;
sum[A[i].x]+=A[i].in;
}
POW(m-L);
cout<<a[1]%MOD<<endl;
return 0;
}