ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

HH去散步

2021-07-28 23:34:35  阅读:290  来源: 互联网

标签:int LL 矩阵 散步 次方 HH MAXM 条边


题目link:https://www.luogu.com.cn/problem/P2151


Part0:

注意题目有重边。


Part1:

首先这道题的题目限制为走过一条边不能按原边返回,这就导致了这个图的有向性,从而得出需要拆边的结论。


Part2:

拆完边后,容易看出如果要想满足题目限制,那么相当于走过第 $i$ 条边后,除了 $i$ 的反向边都可以走。


Part3:

得到上述特性后,再来观察题目,发现数据范围里的 $m$ 的值比较小,且比较的特殊,但是注意,因为通过 Part1Part2 已经拆完边了,那么边的数量需要 $*$ $2$ 。

众所周知,这道题要求的路径方案数和邻接矩阵的幂次方有很大的关系,再加上 $2$ $*$ $m$ $=$ $120$ 这个值,发现 $120^3$ $*$ $log$ $t$ (矩阵快速幂的复杂度为 $O($$n^3$ $log$ $k$$)$)约为 $5e7$ ,不会超时,因此考虑用 $2$ $*$ $m$ 为行列的大小建一个矩阵。


Part4:

建完矩阵后,容易发现矩阵中的元素的一种恰当且显然的意义为如果第 $i$ 条边的终点是第 $j$ 条边的起点 $\&\&$ 第 $i$ 条边和第 $j$ 条边不是反向边,那么矩阵中的第 $i$ 行第 $j$ 列的元素就是 $1$ ,否则为 $0$ 。


Part5:

考虑矩形的 $k$ 次方是什么含义,设 $k$ 次方之后的矩形为 $A$ ,那么容易得出 $A_{i, j}$ 是在图上第 $i$ 条边经过 $k$ $+$ $1$ 条边到达第 $j$ 条边(包括第 $i$ 条边和第 $j$ 条边)的方案数。


Part6:

这样,便容易得出求答案的方法为:在建完矩阵后用矩阵快速幂求出它的 $t$ $-$ $1$ 次方(注意不是 $t$ 次方),枚举起点 $a$ 的所有出边和终点 $b$ 的所有入边,累加计算一下就好了。


Code:

  1 #include <cstdio>
  2 
  3 typedef long long LL;
  4 
  5 const int MAXM = 60;
  6 const LL MOD = 45989;
  7 
  8 int n, m, t, a, b;
  9 int outA[MAXM + 5], inB[MAXM + 5], cntA, cntB, cntEdge;
 10 
 11 struct Node {
 12     int st, to;
 13 };
 14 
 15 struct Mat {
 16 
 17     int N;
 18     LL arr[2 * MAXM + 5][2 * MAXM + 5];
 19 
 20     Mat() {}
 21     Mat(int _N, LL val = 0ll) {
 22         N = _N;
 23         for(int i = 1; i <= N; ++i) {
 24             for(int j = 1; j <= N; ++j) {
 25                 arr[i][j] = (i == j) ? val : 0ll;
 26             }
 27         }
 28     }
 29 
 30     // void print() {
 31     //     for(int i = 1; i <= N; ++i) {
 32     //         for(int j = 1; j <= N; ++j) {
 33     //             printf("%d%c", arr[i][j], (j == N - 1) ? '\n' : ' ');
 34     //         }
 35     //     }
 36     //     puts("");
 37     // }
 38 
 39 };
 40 
 41 Mat operator* (const Mat &A, const Mat &B) {
 42 
 43     Mat res(A.N);
 44 
 45     for(int i = 1; i <= res.N; ++i) {
 46         for(int j = 1; j <= res.N; ++j) {
 47             for(int k = 1; k <= res.N; ++k) {
 48                 res.arr[i][j] += A.arr[i][k] * B.arr[k][j];
 49                 res.arr[i][j] %= MOD;
 50             }
 51         }
 52     }
 53 
 54     return res;
 55 }
 56 
 57 Mat qpow(Mat A, int k) {
 58 
 59     Mat res(A.N, 1ll);
 60 
 61     for(; k; k >>= 1) {
 62         if(k & 1) res = res * A;
 63         A = A * A;
 64     }
 65 
 66     return res;
 67 }
 68 
 69 int main() {
 70 
 71     scanf("%d %d %d %d %d", &n, &m, &t, &a, &b);
 72 
 73     Node edge[2 * MAXM + 5]; // 存边
 74     for(int i = 1, x, y; i <= m; ++i) {
 75         scanf("%d %d", &x, &y);
 76         edge[++cntEdge].st = x, edge[cntEdge].to = y;
 77         edge[++cntEdge].st = y, edge[cntEdge].to = x;
 78         if(x == a || y == a) { // 记录起点和终点的出边和入边
 79             outA[++cntA] = (x == a) ? cntEdge - 1 : cntEdge;
 80         }
 81         if(x == b || y == b) {
 82             inB[++cntB] = (x == b) ? cntEdge : cntEdge - 1;
 83         }
 84     }
 85 
 86     Mat fac(2 * m); // 建矩阵
 87     for(int i = 1; i <= cntEdge; ++i) {
 88         for(int j = 1; j <= cntEdge; ++j) {
 89             if(i == j || ((i & 1) && (j == i + 1)) || ((!(i & 1)) && (j == i - 1))) continue;
 90             if(edge[i].to == edge[j].st) {
 91                 fac.arr[i][j] = 1ll;
 92             }
 93         }
 94     }
 95     
 96     fac = qpow(fac, t - 1); // 矩阵快速幂
 97 
 98     LL ans = 0; // 枚举出入边求解
 99     for(int i = 1; i <= cntA; ++i) {
100         for(int j = 1; j <= cntB; ++j) {
101             ans += fac.arr[outA[i]][inB[j]];
102             ans %= MOD;
103         }
104     }
105 
106     printf("%lld\n", ans);
107 
108     return 0;
109 }

 

标签:int,LL,矩阵,散步,次方,HH,MAXM,条边
来源: https://www.cnblogs.com/qqq1112/p/15072355.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有