Educational Codeforces Round 40 F. Runner's Problem

题意:

给一个$ 3 * m \(的矩阵,问从\)(2,1)$ 出发 走到 \((2,m)\) 的方案数 \(mod 1e9 + 7\), 走的规则和限制如下:

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.

给出了$n $个限制 每个限制如下描述

\(a_i, l_i, r_i l_i <= r_i 1<=a_i <= 3\) 表示第\((a_i, l_i)\) 到 \((a_i, ri)\) 都是不可走的

\(n <= 10000 , m <= 10^{18}\)

思路:

考察没有限制的情况, 写出转移矩阵做快速幂即可

\(\begin{bmatrix} 1& 1 &0 \\ 1& 1 &1 \\ 0& 1 &1 \end{bmatrix}\)

那么给定了限制之后,其实就是转移矩阵在某一段内不会发生变化,处理出每一段做快速幂即可。

最开始我处理每一段的方法有点傻逼,将所有的端点按左开右闭的方式排序,然后对于取出的每一段区间判断第1,2,3行在这段区间内是否有障碍,我采用了对每一行的障碍排序,再用指针的方式来判断是否有障碍。

#include<bits/stdc++.h>
#define LL long long
#define P pair<int,int>
using namespace std;
const int mod = 1e9 + 7;
vector<pair<LL,LL> > a[3];
vector<pair<LL,int> >p;
int n, x;
LL m, l, r;
struct MAT{
int a[3][3];
MAT operator*(const MAT &rhs){
MAT ans;
memset(ans.a, 0, sizeof(ans.a));
for(int i = 0;i < 3;i++){
for(int j = 0;j < 3;j++){
for(int k = 0;k < 3;k++){
ans.a[i][j] = (ans.a[i][j] + 1LL * a[i][k] * rhs.a[k][j] % mod) % mod;
}
}
}
return ans;
}
MAT operator^(LL k){
MAT ans, A = *this;
for(int i = 0;i < 3;i++){
for(int j = 0;j < 3;j++) ans.a[i][j] = (i == j?1:0);
}
for(;k;k >>= 1,A = A * A) if(k & 1) ans = ans * A;
return ans;
}
}mat; int b[3][3];
void init(){
b[0][0] = b[0][1] = 1;
b[1][0] = b[1][1] = b[1][2] = 1;
b[2][1] = b[2][2] = 1;
b[0][2] = b[2][0] = 0;
}
void gao(int row){
for(int i = 0;i < 3;i++) mat.a[row][i] = 0;
}
int main()
{
init();
cin>>n>>m;
for(int i = 0;i < n;i++){
scanf("%d%lld%lld",&x,&l,&r);
a[x - 1].push_back(make_pair(l,r));
p.push_back(make_pair(l - 1, 0));
p.push_back(make_pair(r, 1));
}
p.push_back(make_pair(1,0));
p.push_back(make_pair(m, 1));
sort(p.begin(),p.end());
p.erase(unique(p.begin(),p.end()),p.end()); for(int i = 0;i < 3;i++) sort(a[i].begin(),a[i].end()); LL mxr[3] = {1,1,1};
LL ans[3] = {0,1,0};
int now[3] = {0};
l = p[0].first;
for(int i = 1; i < p.size();i++){
r = p[i].first;
memcpy(mat.a, b, sizeof(b));
for(int j = 0;j < 3;j++){
int &xx = now[j];
while(xx < a[j].size() && a[j][xx].first <= l + 1 &&
(mxr[j] = max(a[j][xx].second,mxr[j])) < r) xx++;
if(xx < a[j].size() && a[j][xx].first <= l + 1 && mxr[j] >= r){
gao(j);
}
} mat = mat ^ (r - l);
LL tmp[3] = {0};
for(int j = 0;j < 3;j++){
for(int k = 0;k < 3;k++) {
tmp[j] += 1LL * mat.a[j][k] * ans[k] % mod;
tmp[j] %= mod; }
memcpy(ans, tmp, sizeof(tmp));
l = p[i].first;
}
cout<<ans[1]<<endl;
return 0;
}

实际上存端点的时候 可以把该端点是起点还是终点以及在哪一行存进去,这样就可以单独每一行进行维护。

当某一行遇到一个起点后,意味着该行从这个点开始都是有障碍的,直到遇到一个终点+1 后面才没有障碍,

这样就容易判断的多。

常用的区间标记操作,只是这里一时没有将这个知识用上来,以致于采用前面的做法觉得复杂很多。

#include<bits/stdc++.h>
#define LL long long
#define P pair<int,int>
using namespace std;
const int mod = 1e9 + 7;
int n, x;
LL m, l, r;
struct MAT{
int a[3][3];
MAT operator*(const MAT &rhs){
MAT ans;
memset(ans.a, 0, sizeof(ans.a));
for(int i = 0;i < 3;i++){
for(int j = 0;j < 3;j++){
for(int k = 0;k < 3;k++){
ans.a[i][j] = (ans.a[i][j] + 1LL * a[i][k] * rhs.a[k][j] % mod) % mod;
}
}
}
return ans;
}
MAT operator^(LL k){
MAT ans, A = *this;
for(int i = 0;i < 3;i++){
for(int j = 0;j < 3;j++) ans.a[i][j] = (i == j?1:0);
}
for(;k;k >>= 1,A = A * A) if(k & 1) ans = ans * A;
return ans;
}
};
struct node{
LL x;
int row, f;
node(LL x,int row,int f):x(x),row(row),f(f){};
bool operator<(const node&rhs)const{
return x < rhs.x;
}
};
vector<node> p;
int main()
{ cin>>n>>m;
for(int i = 0;i < n;i++){
scanf("%d%lld%lld",&x,&l,&r);
p.push_back(node(l, x - 1, 1));
p.push_back(node(r + 1, x - 1, -1));
}
p.push_back(node(m + 1, 1, -1));
sort(p.begin(),p.end());
int isobstacle[4] = {0};
MAT ans;
for(int i = 0;i < 3;i++) for(int j = 0;j < 3;j++) ans.a[i][j] = (i == j?1:0);
l = 1;
for(int i = 0; i < p.size();i++){
r = p[i].x;
LL d = r - l - 1; /// 区间左闭右开
if(d){
MAT mat;
for(int i = 0;i < 3;i++){ // 初始化转移矩阵
for(int j = 0;j < 3;j++) {
if(!isobstacle[i] && abs(i - j) <= 1) mat.a[i][j] = 1;
else mat.a[i][j] = 0;
}
}
ans = (mat ^ d) * ans;
}
isobstacle[p[i].row] += p[i].f;
l = r - 1;
}
cout<<ans.a[1][1]<<endl;
return 0;
}

Educational Codeforces Round 40 F. Runner's Problem的更多相关文章

  1. Educational Codeforces Round 40千名记

    人生第二场codeforces.然而遇上了Education场这种东西 Educational Codeforces Round 40 下午先在家里睡了波觉,起来离开场还有10分钟. 但是突然想起来还 ...

  2. Educational Codeforces Round 40 C. Matrix Walk( 思维)

    Educational Codeforces Round 40 (Rated for Div. 2) C. Matrix Walk time limit per test 1 second memor ...

  3. Educational Codeforces Round 40 (Rated for Div. 2) Solution

    从这里开始 小结 题目列表 Problem A Diagonal Walking Problem B String Typing Problem C Matrix Walk Problem D Fig ...

  4. Educational Codeforces Round 40 I. Yet Another String Matching Problem

    http://codeforces.com/contest/954/problem/I 给你两个串s,p,求上一个串的长度为|p|的所有子串和p的差距是多少,两个串的差距就是每次把一个字符变成另一个字 ...

  5. Educational Codeforces Round 61 F 思维 + 区间dp

    https://codeforces.com/contest/1132/problem/F 思维 + 区间dp 题意 给一个长度为n的字符串(<=500),每次选择消去字符,连续相同的字符可以同 ...

  6. Educational Codeforces Round 51 F. The Shortest Statement(lca+最短路)

    https://codeforces.com/contest/1051/problem/F 题意 给一个带权联通无向图,n个点,m条边,q个询问,询问两点之间的最短路 其中 m-n<=20,1& ...

  7. Educational Codeforces Round 12 F. Four Divisors 求小于x的素数个数(待解决)

    F. Four Divisors 题目连接: http://www.codeforces.com/contest/665/problem/F Description If an integer a i ...

  8. Educational Codeforces Round 26 F. Prefix Sums 二分,组合数

    题目链接:http://codeforces.com/contest/837/problem/F 题意:如题QAQ 解法:参考题解博客:http://www.cnblogs.com/FxxL/p/72 ...

  9. Educational Codeforces Round 9 F. Magic Matrix 最小生成树

    F. Magic Matrix 题目连接: http://www.codeforces.com/contest/632/problem/F Description You're given a mat ...

随机推荐

  1. Java 递归 反射 正则表达式

    一 递归 1. 就是函数自身调用自身 (就是在栈内存中不断的加载同一个函数) 2. 什么时候用递归呢? 当一个功能被重复使用 而每一次使用该功能时的参数不确定 都由上次的功能元素结果来确定 简单说: ...

  2. Java开发工程师(Web方向) - 03.数据库开发 - 期末考试

    期末考试 编程题 本编程题包含4个小题,覆盖知识点从基础的JDBC.连接池到MyBatis. 1(10分) 有一款在线教育产品“天天向上”主要实现了在手机上查看课程表的功能.该产品的后端系统有一张保存 ...

  3. leetcode-全排列详解(回溯算法)

     全排列     给定一个没有重复数字的序列,返回其所有可能的全排列. 示例: 输入: [1,2,3] 输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2 ...

  4. 交换学生 (Foreign Exchange,UVa10763)

    题目描述: 解题思路: 开一个数组,读入一次交换两个数,如果最后数组不变,即符合匹配 #include<iostream> #include<cstdio> #include& ...

  5. CPU设计学习-流水线

    各种名词 标量流水线 超级流水线 超标量流水线与多发射技术 经典五级流水线 IF |Instruction Fetch,取指 ID |Instruction Decode,译码 EX |Execute ...

  6. usb_modeswitch移植

    usb_modeswitch移植 交叉工具链安装 交叉编译安装libsub库 交叉编译安装lib-compat-x.x.x 交叉编译安装usb_modeswitch 交叉编译工具链 为了使编译的程序可 ...

  7. 2019-1-7Xiaomi Mi5 刷全球版MIUI教程

    2019-1-7Xiaomi Mi5 刷全球版MIUI教程 mi5 教程 小书匠  欢迎走进zozo的学习之旅. 前言 固件下载 刷机 刷recovery,root 试用体验 其他参考 前言 机器是老 ...

  8. 学霸系统PipeLine功能规格说明书

    学霸系统PipeLine功能规格说明书共分为以下三部分: 1.产品面向用户群体 2.用户使用说明 3.产品功能具体实现 1.产品面向用户群体 我们这组的项目并不是传统意义上能发布并进行展示的项目,因此 ...

  9. Windows环境下的TensorFlow安装过程

    安装环境 Windows8.1 python3.5.x(TensorFlow only supports version 3.5.x of Python on Windows) pip 9.0.1 t ...

  10. 算法与数据结构实验题 4.1 伊姐姐数字 game

    ★实验任务 伊姐姐热衷于各类数字游戏,24 点.2048.数独等轻轻松松毫无压力.一 日,可爱的小姐姐邀请伊姐姐一起玩一种简单的数字 game,游戏规则如下: 一开始桌上放着 n 张数字卡片,从左到右 ...