Runner's Problem_矩阵快速幂+dp

getchar()读的快
F. Runner's Problem
time limit per test
4 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

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.

Input

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.

Output

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.

Example
Input
Copy
2 5
1 3 4
2 2 3
Output
Copy
2

#include<bits/stdc++.h>
using namespace std;
#define ll long long

const int N=1e4+10;
const int mod=1e9+7;

inline ll read(){
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x;
}

struct P{
    ll x,y,z;
}p[N*2];

bool cmp(P a,P b){
    return a.x<b.x;
}

struct mat{
    int z[3][3];
}x,a[8];

inline mat operator*(const mat &a,const mat& b){
    mat c;
    memset(c.z,0,sizeof(c.z));
    for(int i=0;i<3;i++)for(int j=0;j<3;j++)for(int k=0;k<3;k++)
        c.z[i][k]=(c.z[i][k]+1ll*a.z[i][j]*b.z[j][k])%mod;
    return c;
}


inline mat pw(mat x,ll y){
    mat r;
    for(int i=0;i<3;i++)
    for(int j=0;j<3;j++)
    r.z[i][j]=i==j;
    for(;y;y>>=1,x=x*x)
        if(y&1)r=r*x;
    return r;
}


int u[4];
int cal(){
    return (u[1]?4:0)+(u[2]?2:0)+(u[3]?1:0);
}


int main(){
    freopen("in.txt","r",stdin);
    ll n=read(),m=read();
    //ios::sync_with_stdio(0);
    //cin.tie(0);
    //cout.tie(0);
    for(int i=1;i<=n;i++){
        int x,y=read();
        p[i]=P{read(),y,1};
        p[i+n]=P{read()+1,y,-1};
    }
    sort(p+1,p+1+n+n,cmp);
    for(int i=0;i<8;i++){
        if(!(i&4))a[i].z[0][0]=a[i].z[1][0]=1;
        if(!(i&2))a[i].z[0][1]=a[i].z[1][1]=a[i].z[2][1]=1;
        if(!(i&1))a[i].z[1][2]=a[i].z[2][2]=1;
    }
    x.z[0][1]=1;p[0].x=2;
    /*
    for(int i=1;i<=n+n;i++)
        cout<<p[i].x<<" "<<p[i].y<<" "<<p[i].z<<endl;
        */
    for(int i=1;i<=n+n;i++){
        x=x*pw(a[cal()],p[i].x-p[i-1].x),u[p[i].y]+=p[i].z;
/*
        for(int j=0;j<3;j++){
            for(int k=0;k<3;k++)
                cout<<x.z[j][k]<<" ";
            cout<<endl;
        }
        cout<<"---"<<endl;
        */
    }
    x=x*pw(a[0],m-p[n+n].x+1);
    cout<<x.z[0][1]<<endl;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值