CF821 E. Okabe and El Psy Kongroo 矩阵快速幂

LINK

题意:给出$n$条平行于x轴的线段,终点$k$坐标$(k <= 10^{18})$,现在可以在线段之间进行移动,但不能超出两条线段的y坐标所夹范围,问到达终点有几种方案。

思路:刚开始以为限制只是到达线段上就必须沿线段走,后来才发现是要求走y坐标所夹范围,那么就简单多了,很容易看出是个递推形DP,然而数据量有点大,k为10的18次,一般转移显然不可行。由于是个递推,而且y坐标最大也只有15,故使用矩阵优化递推复杂度即可。

/** @Date    : 2017-07-04 16:06:18
  * @FileName: E 矩阵快速幂 + 递推.cpp
  * @Platform: Windows
  * @Author  : Lweleth ([email protected])
  * @Link    : https://github.com/
  * @Version : $Id$
  */
#include <bits/stdc++.h>
#define LL long long
#define PII pair
#define MP(x, y) make_pair((x),(y))
#define fi first
#define se second
#define PB(x) push_back((x))
#define MMG(x) memset((x), -1,sizeof(x))
#define MMF(x) memset((x),0,sizeof(x))
#define MMI(x) memset((x), INF, sizeof(x))
using namespace std;

const int INF = 0x3f3f3f3f;
const int N = 1e5+20;
const double eps = 1e-8;
const LL mod = 1e9 + 7;
int len;
LL n, k;
struct yuu
{
	LL mat[18][18];
	yuu(){MMF(mat);}
	void init()
	{
		for(int i = 0; i <= 17; i++)
			mat[i][i] = 1;
	}
	yuu operator *(const yuu &b)
	{
		yuu c;
		for(int i = 0; i <= len; i++)
		{
			for(int j = 0; j <= len; j++)
			{
				for(int k = 0; k <= len; k++)
				{
					c.mat[i][j] = (c.mat[i][j] + this->mat[i][k] * b.mat[k][j] % mod) % mod;
				}
			}
		}
		return c;
	}
};
yuu fpow(yuu a, LL n)
{
    yuu res;
    res.init();
	while(n)
	{
		if(n & 1)
			res = res * a;
		a = a * a;
		n >>= 1;
	}
    return res;
}

int main()
{
	while(cin >> n >> k)
	{
		yuu A, B, t;
		for(int i = 0; i < 16; i++)
		{
			int x = i - 1;
			if(x < 0)
				A.mat[i][x + 1] = 1;
			else A.mat[i][x] = 1;
			A.mat[i][x + 1] = A.mat[i][x + 2] = 1;
		}

		t.mat[0][0] = 1;
		int flag = 0;
		for(int i = 0; i < n; i++)
		{
			LL l, r, c;
			scanf("%lld%lld%lld", &l, &r, &c);
			if(flag)
				continue;
			flag = 0;
			r = min(r, k);
			if(r == k)
				flag = 1;
			len = c;
			B = fpow(A, r - l);
			for(int i = c + 1; i < 16; i++)
				t.mat[i][0] = 0;
			B = B * t;
			for(int i = 0; i <= len; i++)
				t.mat[i][0] = B.mat[i][0];

		}
		printf("%lld\n", B.mat[0][0]);
	}

    return 0;
}
时间: 2025-01-05 07:57:34

CF821 E. Okabe and El Psy Kongroo 矩阵快速幂的相关文章

cf 821E Okabe and El Psy Kongroo(矩阵快速幂)

链接:http://codeforces.com/problemset/problem/821/E 分析:由于有边界而且不同段边界还不同,直接算是不行的..k是1e18,dp也不行..用一个16维的向量表示某一列16个位置可能的种类数,到下一列的转移矩阵容易得到,而且在同一段里转移矩阵一样,直接用快速幂算出这一段结束的向量,然后继续推下一段结束的向量.注意特殊情况的处理. 1 #include<iostream> 2 #include<cstring> 3 using namesp

Codeforces Round #420 (Div. 2) E. Okabe and El Psy Kongroo(矩阵)

题目链接:Codeforces Round #420 (Div. 2) E. Okabe and El Psy Kongroo 题意: 在一个二维方格子里有n条线段,有三种走法 (x?+?1,?y?+?1), (x?+?1,?y), or (x?+?1,?y?-?1). 现在要求每次都要在线段下行走,问你有多少种走法, 可以从(0,0)到(k,0). 题解: 考虑dp f[i][j]=f[i-1][j]+f[i-1][j+1]+f[i-1][j-1]. 由于k比较大c比较小,可以考虑用矩阵来优化

Codeforce821E Okabe and El Psy Kongroo

E. Okabe and El Psy Kongroo time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output Okabe likes to take walks but knows that spies from the Organization could be anywhere; that's why he wants to k

[codeforces821E]Okabe and El Psy Kongroo

题意:(0,0)走到(k,0),每一部分有一条线段作为上界,求方案数. 解题关键:dp+矩阵快速幂,盗个图,注意ll 1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<algorithm> 5 #include<cmath> 6 #include<iostream> 7 using namespace std; 8 typedef long lo

Codeforces 821E Okabe and El Psy Kongroo

题意:我们现在位于(0,0)处,目标是走到(K,0)处.每一次我们都可以从(x,y)走到(x+1,y-1)或者(x+1,y)或者(x+1,y+1)三个位子之一.现在一共有N段线段,每条线段都是平行于X轴的.我们如果此时x是在这段线段之内的话,我们此时走到的点(x,y)需要满足0<=y<=Ci.现在保证一段线段的终点,一定是下一段线段的起点.问我们从起点走到终点的行走方案数. dp方程比较显然:dp[i][j]+=dp[i-1][j]+dp[-1][j-1]+dp[i-1][j+1] 之后构造一

矩阵快速幂刷题系列

来源自http://blog.csdn.net/chenguolinblog/article/details/10309423 hdu 1575 Tr A Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5587    Accepted Submission(s): 4200 Problem Description A为一个方阵,则Tr

HDU 1757 A Simple Math Problem (矩阵快速幂)

[题目链接]:click here~~ [题目大意]: If x < 10 f(x) = x. If x >= 10 f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + -- + a9 * f(x-10); 问f(k)%m的值. [思路]:矩阵快速幂,具体思路看代码吧,注意一些细节. 代码: #include<bits/stdc++.h> using namespace std; typedef long long LL; const

Codeforces Round #291 (Div. 2) E - Darth Vader and Tree (DP+矩阵快速幂)

这题想了好长时间,果断没思路..于是搜了一下题解.一看题解上的"快速幂"这俩字,不对..这仨字..犹如醍醐灌顶啊...因为x的范围是10^9,所以当时想的时候果断把dp递推这一方法抛弃了.我怎么就没想到矩阵快速幂呢.......还是太弱了..sad..100*100*100*log(10^9)的复杂度刚刚好. 于是,想到了矩阵快速幂后,一切就变得简单了.就可以把距离<=x的所有距离的点数都通过DP推出来,然后一个快速幂就解决了. 首先DP递推式很容易想到.递推代码如下: for(

POJ 3233 - Matrix Power Series ( 矩阵快速幂 + 二分)

POJ 3233 - Matrix Power Series ( 矩阵快速幂 + 二分) #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long LL; #define MAX_SIZE 30 #define CLR( a, b ) memset( a, b, sizeof(a) ) int MOD = 0; int n, k; st