BZOJ1297 [SCOI2009]迷路

Description

windy在有向图中迷路了。 该有向图有 N 个节点,windy从节点 0 出发,他必须恰好在 T 时刻到达节点 N-1。 现在给出该有向图,你能告诉windy总共有多少种不同的路径吗? 注意:windy不能在某个节点逗留,且通过某有向边的时间严格为给定的时间。

Input

第一行包含两个整数,N T。 接下来有 N 行,每行一个长度为 N 的字符串。 第i行第j列为‘0‘表示从节点i到节点j没有边。 为‘1‘到‘9‘表示从节点i到节点j需要耗费的时间。

Output

包含一个整数,可能的路径数,这个数可能很大,只需输出这个数除以2009的余数。

Sample Input

【输入样例一】

2 2

11

00

【输入样例二】

5 30

12045

07105

47805

12024

12345

Sample Output

【输出样例一】

1

【样例解释一】

0->0->1

【输出样例二】

852

HINT

30%的数据,满足 2 <= N <= 5 ; 1 <= T <= 30 。 100%的数据,满足 2 <= N <= 10 ; 1 <= T <= 1000000000 。

题解

令邻接矩阵中所有k组成的矩阵为$A_k$,$i$阶邻接矩阵为$T_i$,即$T_{i,a,b}$表示从$a$到$b$恰好走$i$的时间的方案数。

那么有

$$T_i = \sum_{j=1}^9 A_j * T_{i-j}$$

我们发现,如果我们把$A_j$和$T_i$都看做单个数,那么这就是经典的线性常系数递推方程,可以用矩阵快速幂解决。

$A_j,T_i$是矩阵也可以这么做,只是1变成了单位矩阵,0变成了零矩阵,递推矩阵变成了“矩阵的矩阵”(当然,在实现上,我们可以把它“拍扁”)。

那么直接强上矩阵快速幂就行了。

附代码:

#include <cstdio>
#include <cstring>
const int N = 15;
const int mod = 2009;
int nn;
struct Matrix{
  int v[N * 9][N * 9];
  Matrix() {
    memset(v, 0, sizeof v);
  }
  friend Matrix operator*(const Matrix &a, const Matrix &b) {
    Matrix ans;
    for (int i = 0; i < nn; ++i)
      for (int j = 0; j < nn; ++j) if (a.v[i][j])
        for (int k = 0; k < nn; ++k)
          ans.v[i][k] = (ans.v[i][k] + a.v[i][j] * b.v[j][k]) % mod;
    return ans;
  }
};
Matrix D;
Matrix ans;
int main() {
  int n, t;
  scanf("%d%d", &n, &t);
  nn = n * 9;
  int x;
  for (int i = 0; i < n; ++i)
    for (int j = 0; j < n; ++j) {
      scanf("%1d", &x);
      if (x) D.v[i][(x - 1) * n + j] = 1;
    }
  for (int i = 0; i < 8 * n; ++i)
    D.v[i + n][i] = 1;
  for (int i = 0; i < n; ++i)
    ans.v[i][i] = 1;
  for (; t; D = D * D, t >>= 1)
    if (t & 1) ans = ans * D;
  printf("%d\n", ans.v[0][n - 1]);
  return 0;
}

  

时间: 2024-10-12 20:14:00

BZOJ1297 [SCOI2009]迷路的相关文章

BZOJ1297 [SCOI2009]迷路 【矩阵优化dp】

题目 windy在有向图中迷路了. 该有向图有 N 个节点,windy从节点 0 出发,他必须恰好在 T 时刻到达节点 N-1. 现在给出该有向图,你能告诉windy总共有多少种不同的路径吗? 注意:windy不能在某个节点逗留,且通过某有向边的时间严格为给定的时间. 输入格式 第一行包含两个整数,N T. 接下来有 N 行,每行一个长度为 N 的字符串. 第i行第j列为'0'表示从节点i到节点j没有边. 为'1'到'9'表示从节点i到节点j需要耗费的时间. 输出格式 包含一个整数,可能的路径数

BZOJ1297 SCOI2009 迷路 矩阵乘法

题意:给定一张有N个点的有向图,求0到N-1长度为T的路径的总条数. 题解:把长度为K的边拆成K条长度为1的边,然后建出邻接矩阵快速幂裸上. #include <cstdio> #include <cstring> #include <cstdlib> #include <climits> #include <iostream> #include <algorithm> using namespace std; #define P(x

bzoj1297: [SCOI2009]迷路(矩阵乘法+拆点)

题目大意:有向图里10个点,点与点之间距离不超过9,问从1刚好走过T距离到达n的方案数. 当时看到这题就想到了某道奶牛题(戳我).这两道题的区别就是奶牛题问的是走T条边,这道题是每条边都有一个边权求走过T边权的方案数...所以可以看成奶牛题相当于这一题里的边权为1的情况. 首先边权为1就把奶牛题的floyd那段改成矩乘就可以了,那么接下来考虑边权不为1的情况,因为边权最多为9,我们就可以把每个点拆成9个点,x[1]~x[9]为x拆完的点,x[i]和x[i+1]连一条边权为1的边,然后x到y有一条

bzoj1297 [SCOI2009]迷路——拆点+矩阵快速幂

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1297 一看感觉是矩阵快速幂之类的,但边权不好处理啊: 普通的矩阵快速幂只能处理边权为1的,所以想办法把边权处理成1: 仔细一看还有一个条件是边权小于10: 所以拆点!把一个点拆成10个点表示到它不同的距离,那么和它相连的那些点就可以跟某个距离的点连边权为1的边: 虽然没有自己想出来,不过1A还是极好的!(因为太简单了) 代码如下: #include<iostream> #include&

bzoj1297 / P4159 [SCOI2009]迷路

P4159 [SCOI2009]迷路 如果边权只有 0/1 那么不就是一个灰常简单的矩阵快速幂吗! 然鹅边权 $<=9$ 所以我们把每个点拆成9个点! 解决~ 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define re register 5 using namespace std; 6 const int mod=2009; 7 int m,n,t;long long q; 8

矩阵乘法专题1——bzoj 1297 [SCOI2009] 迷路题解

题目链接 题意:给两个长度分别为n和m的序列,现在有两种操作:1.分别选择两个序列的一个非空前缀,切两个前缀的最后一位相同,删除之,得到1分(只累计),消耗e:2.直接删除两个序列,消耗值定于两个序列之前删除的元素个数之和,并且使得得到的分有效(之前没有有效分) 分析: 首先,问题其实就是转化成,进行若干次操作1,然后进行操作2 还要找到一个判别标准,来评判较优的状态(贪心) 每次的消耗值比较大,其实可以计算出最大的删除次数,这个值不是很大 状态表示: 简单的,一个状态可以表示为串A的位置.串B

1297: [SCOI2009]迷路

1297: [SCOI2009]迷路 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 652  Solved: 442[Submit][Status] Description windy在有向图中迷路了. 该有向图有 N 个节点,windy从节点 0 出发,他必须恰好在 T 时刻到达节点 N-1. 现在给出该有向图,你能告诉windy总共有多少种不同的路径吗? 注意:windy不能在某个节点逗留,且通过某有向边的时间严格为给定的时间. Input

[BZOJ 1297][SCOI2009]迷路

1297: [SCOI2009]迷路 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1418  Solved: 1017[Submit][Status][Discuss] Description windy在有向图中迷路了. 该有向图有 N 个节点,windy从节点 0 出发,他必须恰好在 T 时刻到达节点 N-1. 现在给出该有向图,你能告诉windy总共有多少种不同的路径吗? 注意:windy不能在某个节点逗留,且通过某有向边的时间严格为给定

BZOJ 1297: [SCOI2009]迷路 [矩阵快速幂]

Description windy在有向图中迷路了. 该有向图有 N 个节点,windy从节点 0 出发,他必须恰好在 T 时刻到达节点 N-1. 现在给出该有向图,你能告诉windy总共有多少种不同的路径吗? 注意:windy不能在某个节点逗留,且通过某有向边的时间严格为给定的时间. Input 第一行包含两个整数,N T. 接下来有 N 行,每行一个长度为 N 的字符串. 第i行第j列为'0'表示从节点i到节点j没有边. 为'1'到'9'表示从节点i到节点j需要耗费的时间. Output 包