1.题目描写叙述: pid=5411">点击打开链接
2.解题思路:本题实际是是已知一张无向图。问长度小于等于m的路径一共同拥有多少条。
能够通过建立转移矩阵利用矩阵高速幂解决。当中,转移矩阵就是输入时候的邻接矩阵,同一时候多添加最后一列,都置为1。表示从i開始的,长度不超过M的路径的答案总数(最后一行的1~n列为全0行,能够理解为空集),那么把转移矩阵自乘M-1次后就是路径长度为M的转移矩阵(这里的路径长度指的是顶点的个数。顶点=边数+1,因此仅仅须要乘M-1次)。
为何便于求和。能够设置一个第一行都为1的矩阵B,B*Trans后B[1][n+1]就是A的第n+1列全部项的和。输出就可以。
3.代码:
#define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<algorithm> #include<cassert> #include<string> #include<sstream> #include<set> #include<vector> #include<stack> #include<map> #include<queue> #include<deque> #include<cstdlib> #include<cstdio> #include<cstring> #include<cmath> #include<ctime> #include<cctype> #include<functional> using namespace std; #define me(s) memset(s,0,sizeof(s)) #define pb push_back typedef long long ll; typedef unsigned int uint; typedef unsigned long long ull; typedef pair <ll, int> P; const int MOD = 2015; const int N = 100000 + 5; const int sz = 55; struct Matrix { int m[sz][sz]; Matrix(){ me(m); } Matrix operator*(const Matrix&b) { Matrix c; for (int i = 0; i<sz; i++) for (int j = 0; j<sz; j++) for (int k = 0; k<sz; k++) c.m[i][j] = (c.m[i][j] + m[i][k] * b.m[k][j]) % MOD; return c; } Matrix get(int n) { Matrix res, b = *this; for (int i = 0; i<sz; i++)res.m[i][i] = 1; while (n>0) { if (n & 1)res = res*b; b = b*b; n >>= 1; } return res; } }; int main() { int T; for (scanf("%d", &T); T--;) { Matrix a, b; int m, n, cnt, x; scanf("%d%d", &n, &m); for (int i = 1; i <= n + 1; i++)a.m[i][n + 1] = 1; //第n+1列都设置为1。便于求和 for (int i = 1; i <= n; i++) { scanf("%d", &cnt); for (int j = 1; j <= cnt; j++) { scanf("%d", &x); a.m[i][x] = 1; } } for (int i = 1; i <= n + 1; i++)//b矩阵第1行所有为1,便于对a矩阵的第n+1列求和 b.m[1][i] = 1; a = a.get(m); b = b*a; if (m == 1)printf("%d\n", n + 1); else printf("%d\n", b.m[1][n + 1]); } }
时间: 2024-10-11 13:46:01