F. Runner's Problem
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
有一个3×M的田野
一开始你在(1,2)位置
如果你在(i,j)位置
在不出界的前提下,可以走到(i+1,j),(i+1,j±1)
有n段障碍,障碍不能走
询问从(1,2)到达(M,2)的方案数
n<=10^4,M<=10^18。
题解:首先可以列出很简单的转移方程,然后想到用矩阵优化,但是由于有坏点,不能走,所以需要离散化这些坏点,然后分段快速幂即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
#define x0 x0___
#define y0 y0___
#define pb push_back
#define SZ(X) ((int)X.size())
#define mp make_pair
#define fi first
#define se second
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pli pair<ll,int>
#define pil pair<int,ll>
#define ALL(X) X.begin(),X.end()
#define RALL(X) X.rbegin(),X.rend()
#define rep(i,j,k) for(int i = j;i <= k;i ++)
#define per(i,j,k) for(int i = j;i >= k;i --)
#define mem(a,p) memset(a,p,sizeof(a))
const ll MOD = 1E9 + 7;
ll qmod(ll a,ll b,ll c) {ll res=1;a%=c; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%c;a=a*a%c;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
template<typename T, typename S>
void upmax(T& a,S b){if(a<b) a=b;}
template<typename T, typename S>
void upmin(T& a,S b){if(a>b) a=b;}
template<typename T>
void W(T b){cout << b << endl;}
void gettle() {while(1);}
void getre() {int t=0;t/=t;}
/
/
/
/
struct Matrix
{
ll a[4][4];
void clear() {
mem(a,0);
}
void gao() {
rep(i,1,3) rep(j,1,3) a[i][j] = 1;
a[1][3] = a[3][1] = 0;
}
void init() {
clear();
a[1][1]=a[2][2]=a[3][3]=1;
}
Matrix operator * (const Matrix & x) const {
Matrix res; res.clear();
rep(i,1,3) rep(j,1,3) rep(k,1,3) res.a[i][j] = (res.a[i][j]+a[i][k]*x.a[k][j]%MOD)%MOD;
return res;
}
Matrix mpow(Matrix x, ll k) {
Matrix res; res.init();
while(k) {
if(k&1) res=res*x;
x=x*x; k>>=1;
}
return res;
}
};
const int N = 2E5 + 7;
ll bad[4][N];
ll V[N];
int main()
{
ll n, m;
cin >> n >> m;
vector<tuple<int,ll,ll> > till;
int tot(0);
rep (i,1,n) {
int opt;
ll l,r;
cin >> opt >> l >> r;
V[++tot] = l - 1;
V[++tot] = r;
till.pb({opt,l,r});
}
V[++tot] = 1;
V[++tot] = m;
sort(V+1, V+1+tot);
int nn = unique(V+1,V+1+tot) - (V+1); //不重复数的个数,注意下标
rep (i,1,n) {
int opt;
ll l, r;
tie(opt,l,r) = till[i-1];
ll _l = lower_bound(V+1,V+1+nn, l) - V;
ll _r = lower_bound(V+1,V+1+nn, r) - V;
bad[opt][_l] ++;
bad[opt][_r+1] --;
}
Matrix ans; ans.clear(); ans.a[2][1] = 1LL;
ll now[4];
mem(now,0);
rep (i,2,nn) {
ll len = V[i] - V[i-1];
Matrix tmp; tmp.gao();
rep (j,1,3) {
now[j] += bad[j][i];
if(now[j]) tmp.a[j][1] = tmp.a[j][2] = tmp.a[j][3] = 0;
}
tmp = tmp.mpow(tmp, len);
ans = tmp * ans;
}
cout << ans.a[2][1] << endl;
return 0;
}
我王企鹅无群
题解: