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. UpdateLog

    2014-10-20 增加数据适配器,使支持多数据库类型2015-01-08 增加没有主键ID的抽象类,使能自义主键字段实现MODEL 增加虚拟字段转换,将指定函数或语法转换为对象属性,灵活性更大了 ...

  2. Qt 计算两个日前间隔天数

    某一个大神写的 改写了一点 请无视注释 //时间计算法则 /********************************************************************** ...

  3. selenide 自动化测试进阶一: 查找元素和相关操作

    基础环境配置和举例请移步:https://www.cnblogs.com/davice/p/9298742.html 提到自动化有些测试同学就会问,我会使用工具录制做自动化,我会用工具或插件识别元素. ...

  4. pyhon文件操作典型代码实现(非常经典!)

    1. 编写一个程序,统计当前目录下每个文件类型的文件数,程序实现如图: 实现代码: import os all_files = os.listdir(os.chdir("D:\\" ...

  5. .NET中发送邮件的实现

    .NET中发送邮件 注意: 1.引用下列命名空间: using System.Net; using System.Net.Mail; 2.确保你使用的发送邮件的邮箱开启了stamp服务等. /// & ...

  6. Java Web开发框架Spring+Hibernate整合效果介绍(附源码)(已过期,有更好的)

    最近花了一些时间整合了一个SpringMVC+springAOP+spring security+Hibernate的一套框架,之前只专注于.NET的软件架构设计,并没有接触过Java EE,好在有经 ...

  7. 统计学习五:3.决策树的学习之CART算法

    全文引用自<统计学习方法>(李航) 分类与回归树(classification and regression tree, CART)模型是由Breiman等人于1984年提出的另一类决策树 ...

  8. C语言链接数据库

    一.解释一下函数功能和用法 1.mysql_real_connect 函数原型:MYSQL *mysql_real_connect(MYSQL *mysql, const char *host, co ...

  9. VBA基础之Excel 工作表(Sheet)的操作(二)

    二. Excel 工作表(Sheet)的操作1. Excel 添加工作表(Sheet) 方法名 参数 参数值 说明 Add Before 工作表名称 在指定的工作表前面插入新的工作表 After 工作 ...

  10. Android之Bluetooth编程

    Android Bluetopth 编程大牛文章 http://my.oschina.net/u/994235/blog?catalog=313604 ViewGroup 相关资料 : http:// ...