题目链接:http://codeforces.com/contest/821/problem/E

题意:起初在(0,0),现在要求走到(k,0),问你存在多少种走法。 其中有n条线段,每条线段为(a,y)->(b,y),代表如果x坐标走到[a,b]之间时,处于的y坐标要小于这个线段的y坐标,就是只能在线段的下方走(包括刚好在线段上),并且前一个段线段的x坐标与后一个线段的x坐标相同。

思路:dp[i][j]代表从起点走到(i,j)时的走法,那么dp[i][j]=dp[i-1][j]+dp[i-1][j-1]+dp[i-1][j+1]。由于dp[i]只由dp[i-1]转移过来,所以可以忽略i这一维,由于y坐标比较少,x坐标比较大,所以通过矩阵快速幂来优化。

#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<queue>
#include<vector>
#include<time.h>
#include<stack>
#include<cmath>
using namespace std;
typedef long long int LL;
const LL INF = ;
const int MAXN = + ;
const int MAXX = + ;
const int mod = 1e9 + ;
struct Node{
LL l, r, y;
}P[MAXN];
struct Matrix{
int row, col;
LL m[MAXX][MAXX];
void init(int row, int col){
this->row = row;
this->col = col;
for (int i = ; i < row; ++i)
for (int j = ; j < col; ++j)
m[i][j] = ;
}
}C;
Matrix operator*(const Matrix & a, const Matrix& b){
Matrix res;
res.init(a.row, b.col);
for (int k = ; k < a.col; ++k){
for (int i = ; i < res.row; ++i){
if (a.m[i][k] == ) continue;
for (int j = ; j < res.col; ++j){
if (b.m[k][j] == ) continue;
res.m[i][j] = (a.m[i][k] * b.m[k][j] + res.m[i][j]) % mod;
}
}
}
return res;
}
Matrix operator+(const Matrix & a, const Matrix& b){
Matrix res;
res.init(a.row, b.col);
for (int i = ; i< a.col; ++i){
for (int j = ; j < res.row; ++j){
res.m[i][j] = (a.m[i][j] + b.m[i][j]) % mod;
}
}
return res;
}
Matrix Mpow(Matrix A, LL n){
Matrix ans = A, p = A;
while (n){
if (n & ){
ans = ans*p; n--;
}
n >>= ; p = p*p;
}
return ans;
}
int main(){
//#ifdef kirito
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
//#endif
// int start = clock();
int n; LL k;
while (~scanf("%d%lld",&n,&k)){
for (int i = ; i < n; i++){
scanf("%lld%lld%lld", &P[i].l, &P[i].r, &P[i].y);
}
C.init(, ); C.m[][] = ;
for (int i = ; i < n; i++){
if (P[i].l >= k){
break;
}
Matrix res; res.init(, );
for (int j = ; j < ; j++){
if (j>P[i].y){
break;
}
for (int q = -; q <= ; q++){
if (j + q >= && j + q <= P[i].y){
res.m[j][j + q] = ;
}
}
}
res = Mpow(res, min(k,P[i].r) - min(k,P[i].l)-); //超过k的不需计算
for (int j = P[i].y + ; j < ; j++){ //超过线段y坐标的走法不存在,置0
C.m[j][] = ;
}
C = C*res;
}
printf("%lld\n", C.m[][]);
}
//#ifdef LOCAL_TIME
// cout << "[Finished in " << clock() - start << " ms]" << endl;
//#endif
return ;
}

最新文章

  1. ArcGIS Engine开发之属性查询
  2. windows配置nginx实现负载均衡集群
  3. delphi 博客地址收藏
  4. jquery 显示“加载状态 结束”
  5. android图片的压缩和水印
  6. Asp.net MVC4 捆绑和压缩
  7. jsp获取一个对象和list对象
  8. 将图片转为ASCII字符画
  9. 自动化运维:使用psutil和paramiko读取远程主机信息
  10. 解除织梦dedeCMS标题/关键词/ 简略标题长度限制听语音
  11. API创建/更新员工薪水
  12. &quot;《算法导论》之‘线性表’&quot;:基于动态分配的数组的顺序表
  13. 【转载】Hadoop 2.7.3 和Hbase 1.2.4安装教程
  14. flask 对URL进行安全验证
  15. NTP服务器时间集群借节点之间同步
  16. firefor打不开问题
  17. Session超时问题(AOP 过滤器)
  18. [BZOJ 5323][Jxoi2018]游戏
  19. hdu 4003 Find Metal Mineral 树形dp ,*****
  20. 在32位Centos6.4上安装GraphicsMagick

热门文章

  1. Python---基础-小游戏用户猜数字
  2. Test 6.24 T2 集合
  3. Task6.神经网络基础
  4. c#Main()方法,java 是小写main
  5. Python_011(生成器)
  6. 如何实现全屏遮罩(附Vue.extend和el-message源码学习)
  7. Spring JDBCTemplate 简单使用
  8. windows 命令端口映射
  9. firefox SSL_ERROR_RX_RECORD_TOO_LONG burpsuit 报错 解决方案
  10. WCF身份验证之用户名密码认证