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 ...
随机推荐
- hadoop 家族图
hadoop家族
- selenium,unittest——驾照科目一网上答题自动化
需求很简单,所有题目全选A,然后点提交出分,校验是否到达出分这步 遇到的坑有这几个,一个是assertIn哪个是校验哪个是文本要分清,还有code的编码统一到Unicode,最后就是xpath定位各个 ...
- 怎样用Eclipse将Java源代码生成可执行文件[转]
eclipse将java源代码生成jar可执行文件 用eclipse做了一个web项目的自动化测试,自己用的时候倒是很方便,打开eclipse直接运行即可,但是分享给其他小伙伴用的时候就不太方便,希望 ...
- 41. Maximum Subarray
Description Given an array of integers, find a contiguous subarray which has the largest sum. The su ...
- 【20180807模拟测试】t1 function
low逼的我也只能写这样的水题... 题面 对于一个整数,定义 f(x)为他的每个数位的阶乘的乘积.例如 f(135)=1! * 3! * 5! =720.给出一个数 a(可以包含前缀零),a 满足他 ...
- 剑指offer-包含min函数的栈20
题目描述 定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1)). class Solution: def __init__(self): self.st ...
- Java开发中用的比较多的数据结构
java 中几种常用数据结构 2016年07月11日 09:11:27 阅读数:83211 标签: 数据结构java 更多 个人分类: 自行学习 JAVA中常用的数据结构(java.util. 中 ...
- LeetCode - 167. Two Sum II - Input array is sorted - O(n) - ( C++ ) - 解题报告
1.题目大意 Given an array of integers that is already sorted in ascending order, find two numbers such t ...
- canvas学习(四):高级属性
一:阴影 示例:绘制一个带有阴影的正方形 var canvas = document.getElementById("myCanvas") var ctx = canvas.get ...
- 自测之Lesson12:信号量
题目:创建一个包含5个信号量的信号集. 完成代码: #include <stdio.h> #include <sys/ipc.h> #include <sys/sem.h ...