Educational Codeforces Round 40 F. Runner's Problem
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的更多相关文章
- Educational Codeforces Round 40千名记
人生第二场codeforces.然而遇上了Education场这种东西 Educational Codeforces Round 40 下午先在家里睡了波觉,起来离开场还有10分钟. 但是突然想起来还 ...
- 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 ...
- Educational Codeforces Round 40 (Rated for Div. 2) Solution
从这里开始 小结 题目列表 Problem A Diagonal Walking Problem B String Typing Problem C Matrix Walk Problem D Fig ...
- Educational Codeforces Round 40 I. Yet Another String Matching Problem
http://codeforces.com/contest/954/problem/I 给你两个串s,p,求上一个串的长度为|p|的所有子串和p的差距是多少,两个串的差距就是每次把一个字符变成另一个字 ...
- Educational Codeforces Round 61 F 思维 + 区间dp
https://codeforces.com/contest/1132/problem/F 思维 + 区间dp 题意 给一个长度为n的字符串(<=500),每次选择消去字符,连续相同的字符可以同 ...
- Educational Codeforces Round 51 F. The Shortest Statement(lca+最短路)
https://codeforces.com/contest/1051/problem/F 题意 给一个带权联通无向图,n个点,m条边,q个询问,询问两点之间的最短路 其中 m-n<=20,1& ...
- 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 ...
- Educational Codeforces Round 26 F. Prefix Sums 二分,组合数
题目链接:http://codeforces.com/contest/837/problem/F 题意:如题QAQ 解法:参考题解博客:http://www.cnblogs.com/FxxL/p/72 ...
- Educational Codeforces Round 9 F. Magic Matrix 最小生成树
F. Magic Matrix 题目连接: http://www.codeforces.com/contest/632/problem/F Description You're given a mat ...
随机推荐
- Java 递归 反射 正则表达式
一 递归 1. 就是函数自身调用自身 (就是在栈内存中不断的加载同一个函数) 2. 什么时候用递归呢? 当一个功能被重复使用 而每一次使用该功能时的参数不确定 都由上次的功能元素结果来确定 简单说: ...
- Java开发工程师(Web方向) - 03.数据库开发 - 期末考试
期末考试 编程题 本编程题包含4个小题,覆盖知识点从基础的JDBC.连接池到MyBatis. 1(10分) 有一款在线教育产品“天天向上”主要实现了在手机上查看课程表的功能.该产品的后端系统有一张保存 ...
- leetcode-全排列详解(回溯算法)
全排列 给定一个没有重复数字的序列,返回其所有可能的全排列. 示例: 输入: [1,2,3] 输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2 ...
- 交换学生 (Foreign Exchange,UVa10763)
题目描述: 解题思路: 开一个数组,读入一次交换两个数,如果最后数组不变,即符合匹配 #include<iostream> #include<cstdio> #include& ...
- CPU设计学习-流水线
各种名词 标量流水线 超级流水线 超标量流水线与多发射技术 经典五级流水线 IF |Instruction Fetch,取指 ID |Instruction Decode,译码 EX |Execute ...
- usb_modeswitch移植
usb_modeswitch移植 交叉工具链安装 交叉编译安装libsub库 交叉编译安装lib-compat-x.x.x 交叉编译安装usb_modeswitch 交叉编译工具链 为了使编译的程序可 ...
- 2019-1-7Xiaomi Mi5 刷全球版MIUI教程
2019-1-7Xiaomi Mi5 刷全球版MIUI教程 mi5 教程 小书匠 欢迎走进zozo的学习之旅. 前言 固件下载 刷机 刷recovery,root 试用体验 其他参考 前言 机器是老 ...
- 学霸系统PipeLine功能规格说明书
学霸系统PipeLine功能规格说明书共分为以下三部分: 1.产品面向用户群体 2.用户使用说明 3.产品功能具体实现 1.产品面向用户群体 我们这组的项目并不是传统意义上能发布并进行展示的项目,因此 ...
- Windows环境下的TensorFlow安装过程
安装环境 Windows8.1 python3.5.x(TensorFlow only supports version 3.5.x of Python on Windows) pip 9.0.1 t ...
- 算法与数据结构实验题 4.1 伊姐姐数字 game
★实验任务 伊姐姐热衷于各类数字游戏,24 点.2048.数独等轻轻松松毫无压力.一 日,可爱的小姐姐邀请伊姐姐一起玩一种简单的数字 game,游戏规则如下: 一开始桌上放着 n 张数字卡片,从左到右 ...