[HDU2157]How many ways??(DP + 矩阵优化)

传送门

k < 20

k这么小,随便dp一下就好了。。。

dp[i][j][k]表示从i到j经过k个点的方案数

4重循环。。

但是如果k很大就不好弄了

把给定的图转为邻接矩阵,即A(i,j)=1当且仅当存在一条边i->j。令C=A*A,那么C(i,j)=ΣA(i,k)*A(k,j),实际上就等于从点i到点j恰好经过1个点的路径数(枚举k为中转点)。类似地,C*A的第i行第j列就表示从i到j经过2个点的路径数。同理,如果要求经过k步的路径数,我们只需要二分求出A^k即可。

#include <cstdio>
#include <cstring>
#define p 1000

int n, m, k, T;

struct Matrix
{
	int n, m;
	int a[21][21];
	Matrix()
	{
		n = m = 0;
		memset(a, 0, sizeof(a));
	}
}ans;

inline Matrix operator * (Matrix x, Matrix y)
{
	int i, j, k;
	Matrix ans;
	ans.n = x.n;
	ans.m = y.m;
	for(i = 1; i <= x.n; i++)
		for(j = 1; j <= y.m; j++)
			for(k = 1; k <= y.n; k++)
				ans.a[i][j] = (ans.a[i][j] + x.a[i][k] * y.a[k][j]) % p;
	return ans;
}

inline Matrix operator ^ (Matrix x, int y)
{
	int i;
	Matrix ans;
	ans.n = ans.m = n;
	for(i = 1; i <= n; i++) ans.a[i][i] = 1;
	for(; y; y >>= 1)
	{
		if(y & 1) ans = x * ans;
		x = x * x;
	}
	return ans;
}

int main()
{
	int i, x, y;
	while(~scanf("%d %d", &n, &m) && n + m)
	{
		Matrix c;
		c.n = c.m = n;
		for(i = 1; i <= m; i++)
		{
			scanf("%d %d", &x, &y);
			c.a[x + 1][y + 1] = 1;
		}
		scanf("%d", &T);
		for(i = 1; i <= T; i++)
		{
			scanf("%d %d %d", &x, &y, &k);
			ans = c ^ k;
			printf("%d\n", ans.a[x + 1][y + 1]);
		}
	}
	return 0;
}

  

时间: 2024-10-20 07:04:39

[HDU2157]How many ways??(DP + 矩阵优化)的相关文章

[Vijos1067]Warcraft III 守望者的烦恼(DP + 矩阵优化)

传送门 可知 f[i] = f[i - 1] + f[i - 2] + ... + f[i - k] 直接矩阵优化就好了 #include <cstdio> #include <cstring> #define p 7777777 #define LL long long int n, k; struct Matrix { int n, m; LL a[11][11]; Matrix() { n = m = 0; memset(a, 0, sizeof(a)); } }; inli

ZOJ 3690 Choosing number(dp矩阵优化)

Choosing number Time Limit: 2 Seconds      Memory Limit: 65536 KB There are n people standing in a row. And There are m numbers, 1.2...m. Every one should choose a number. But if two persons standing adjacent to each other choose the same number, the

POJ3744 Scout YYF I (概率DP + 矩阵优化)

题目链接: http://poj.org/problem?id=3744 题意: 有一段路,路上有n个陷阱,每一次只能向前走一步或者两步,求安全走过这段路的改路 分析: 设dp[i]表示安全走过第i个陷阱的概率 那么dp[i+1]=dp[i]*(1-p(走到第i+1个陷阱)) 因为每次只能走一步或者两步,所有安全走过第i个陷阱后的位置一定在a[i]+1;\ 其中a[i]表示第i个陷阱的位置 求从a[i]+1,走到a[i+1]的概率的时候我们需要用到矩阵来经行优化 ans[i]表示走到位置i的概率

bzoj 1009 DP 矩阵优化

原来的DP: dp[i][j]表示长度为i的合法串,并且它的长度为j的后缀是给定串的长度为j的前缀. 转移: i==0 dp[0][0] = 1 dp[0][1~m-1] = 0 i>=1 dp[i][0] = dp[i-1][0]*10-dp[i-1][m-1] dp[i][1] = dp[i-1][0]-(a[m]==a[1])*dp[i-1][m-1] dp[i][2] = dp[i-1][1]-(a[m-1~m]==a[1~2])*dp[i-1][m-1] dp[i][3] = dp[i

[POJ2778]DNA Sequence(AC自动机 + DP + 矩阵优化)

传送门 AC自动机加DP就不说了 注意到 m <= 10,所以模式串很少. 而 n 很大就需要 log 的算法,很容易想到矩阵. 但是该怎么构建? 还是矩阵 A(i,j) = ∑A(i,k) * A(k,j),那么i到j的方案数就是j到k的方案数称k到j的方案数,那么直接矩阵快速幂即可 #include <queue> #include <cstdio> #include <cstring> #define N 100001 #define p 100000 #d

HDU----(2157)How many ways??(快速矩阵幂)

How many ways?? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1562    Accepted Submission(s): 546 Problem Description 春 天到了, HDU校园里开满了花, 姹紫嫣红, 非常美丽. 葱头是个爱花的人, 看着校花校草竞相开放, 漫步校园, 心情也变得舒畅. 为了多看看这

【POJ】3744 Scout YYF I (概率DP+矩阵优化)

题目大意:走一步概率为p,走两步为1-p,x[i]代表第i个地雷的位置,求走出的概率为多少. 思路:设p[i]为走到i格的概率,那么走出去的概率为(1-p[x[i]])累乘 假如把整个路程分成若干段的话,以地雷为节点,可以发现p(x[i-1]~x[i])累乘,也是答案.可能说的不是很清楚,代码中可以看的比较清楚. 这边要说的是由于数据量比较大,并且数据之间又是乘法,所以会造成超时的情况. 一个方法便是利用矩阵快速幂的方法. 这边我介绍一下这个矩阵的一些意义吧.方法就不说了,大家可以百度大神代码,

BZOJ1875 [SDOI2009]HH去散步 【dp + 矩阵优化】

题目 HH有个一成不变的习惯,喜欢饭后百步走.所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离. 但 是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回. 又因为HH是个喜欢变化的人,所以他每 天走过的路径都不完全一样,他想知道他究竟有多 少种散步的方法. 现在给你学校的地图(假设每条路的长度都 是一样的都是1),问长度为t,从给定地 点A走到给定地点B共有多少条符合条件的路径 输入格式 第一行:五个整数N,M,t,A,B. N表示学校里的路口的个数 M表示学校里的 路的

POJ3735 Training little cats DP,矩阵快速幂,稀疏矩阵优化

题目大意是,n只猫,有k个动作让它们去完成,并且重复m次,动作主要有三类gi,ei,s i j,分别代表第i只猫获得一个花生,第i只猫吃掉它自己所有的花生,第i只和第j只猫交换彼此的花生.k,n不超过100,m不超过1000,000,000,计算出最后每只猫还剩下多少个花生. 我们假设一个n维向量P,每个分量的值代表这n只猫所拥有的花生数,那么对于gi操作其实就是在第i维分量上加上1:对于ei,那就是在第i维分量上乘以0,说到这里,有木有感觉这很像3D坐标转化中的平移矩阵和缩放矩阵?没错,就是这