BZOJ 1875: [SDOI2009]HH去散步( dp + 矩阵快速幂 )

BZOJ 1875: [SDOI2009]HH去散步( dp + 矩阵快速幂 )

把双向边拆成2条单向边, 用边来转移...然后矩阵乘法+快速幂优化

---------------------------------------------------------------------------------------------

#include<cstdio>
#include<cstring>
#include<algorithm>
 
using namespace std;
 
const int MOD = 45989;
const int maxn = 29;
const int maxm = 129;
 
int N, M, T, A, B;
int U[maxm], V[maxm], Id[maxm], f[maxm];
 
struct matrix {
int a[maxm][maxm];
matrix() {
memset(a, 0, sizeof a);
}
matrix operator * (const matrix &o) const {
matrix ret;
for(int i = 0; i < M; i++)
for(int k = 0; k < M; k++)
for(int j = 0; j < M; j++)
(ret.a[i][j] += a[i][k] * o.a[k][j]) %= MOD;
return ret;
}
matrix operator = (const matrix &o) {
memcpy(a, o.a, sizeof a);
return *this;
}
void Unit() {
for(int i = 0; i < M; i++)
a[i][i] = 1;
}
} mat, base;
 
void init() {
scanf("%d%d%d%d%d", &N, &M, &T, &A, &B);
for(int i = 0; i < M; i++) {
scanf("%d%d", U + i, V + i);
U[i + M] = V[i];
V[i + M] = U[i];
Id[i] = Id[i + M] = i;
}
}
 
int main() {
init();
M <<= 1;
for(int i = 0; i < M; i++)
for(int j = 0; j < M; j++)
if(Id[i] != Id[j] && V[i] == U[j]) base.a[j][i] = 1;
mat.Unit();
for(T--; T; T >>= 1, base = base * base)
if(T & 1) mat = mat * base;
memset(f, 0, sizeof f);
for(int i = 0; i < M; i++)
if(U[i] == A) f[i] = 1;
int ans = 0;
for(int i = 0; i < M; i++) if(V[i] == B)
for(int j = 0; j < M; j++)
if((ans += mat.a[i][j] * f[j]) >= MOD) ans -= MOD;
printf("%d\n", ans);
return 0;

---------------------------------------------------------------------------------------------

1875: [SDOI2009]HH去散步

Time Limit: 20 Sec  Memory Limit: 64 MB
Submit: 1027  Solved: 469
[Submit][Status][Discuss]

Description

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

Input

第一行:五个整数N,M,t,A,B。其中N表示学校里的路口的个数,M表示学校里的 路的条数,t表示HH想要散步的距离,A表示散步的出发点,而B则表示散步的终点。 接下来M行,每行一组Ai,Bi,表示从路口Ai到路口Bi有一条路。数据保证Ai = Bi,但 不保证任意两个路口之间至多只有一条路相连接。 路口编号从0到N − 1。 同一行内所有数据均由一个空格隔开,行首行尾没有多余空格。没有多余空行。 答案模45989。

Output

一行,表示答案。

Sample Input

4 5 3 0 0
0 1
0 2
0 3
2 1
3 2

Sample Output

4

HINT

对于30%的数据,N ≤ 4,M ≤ 10,t ≤ 10。
对于100%的数据,N ≤ 20,M ≤ 60,t ≤ 230,0 ≤ A,B

Source

上一篇:spark streaming 实例


下一篇:Codeforces Round #498 (Div. 3)