BZOJ 1875[SDOI2009]HH去散步

题面:

1875: [SDOI2009]HH去散步

Time Limit: 20 Sec  Memory Limit: 64 MB
Submit: 1750  Solved: 851
[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。
N ≤ 20,M ≤ 60,t ≤ 2^30,0 ≤ A,B

Output

一行,表示答案。

Sample Input

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

Sample Output

4

HINT

这不是裸的矩阵乘(要是就好了),要建立边的矩阵。

若v[i]==u[j],则g[i][j]=1(不能反过来,因为存的是单向边)。

1*cnt的矩阵f[1][i]=[u[i]==start]。

ans=f*g^(step-1)。答案为ans[1][i](v[i]==end)的和。

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string.h>
 4 using namespace std;
 5 #define mod 45989
 6 int u[151],v[151];
 7 int n,m,cnt,s,t,e;
 8 int sum;
 9 int belong[151];
10 struct martix
11 {
12     int a[151][151];
13     martix()
14     {
15         memset(a,0,sizeof(a));
16     }
17 };
18 martix multiplay(martix x,martix y)
19 {
20     martix z;
21     for(int i=1;i<=cnt;i++)  
22         for(int j=1;j<=cnt;j++)
23             for(int k=1;k<=cnt;k++)
24                 z.a[i][j]=(z.a[i][j]+x.a[i][k]*y.a[k][j])%mod;
25     return z;
26 }
27 martix qpow(martix x,int y)
28 {
29     martix a,z;
30     z=x;
31     for(int i=0;i<=150;i++)
32         a.a[i][i]=1;
33     while(y)
34     {
35         if(y&1)
36         {
37             a=multiplay(a,z);
38             --y;
39         }
40         z=multiplay(z,z);
41         y>>=1;
42     }
43     return a;
44 }
45 int main()
46 {
47     int x,y;
48     scanf("%d%d%d%d%d",&n,&m,&t,&s,&e);
49     martix ans;
50     martix bns;
51     for(int i=1;i<=m;i++)
52     {
53         scanf("%d%d",&x,&y);
54         u[++cnt]=x;
55         v[cnt]=y;
56         belong[cnt]=i;
57         u[++cnt]=y;
58         v[cnt]=x;
59         belong[cnt]=i;
60     }
61     for(int i=1;i<=cnt;i++)
62         for(int j=1;j<=cnt;j++)
63             if(v[i]==u[j]&&belong[i]!=belong[j])
64                 ans.a[i][j]=1;
65     for(int i=1;i<=cnt;i++)
66         if(u[i]==s)
67             bns.a[1][i]=1;
68     ans=qpow(ans,t-1);
69     ans=multiplay(bns,ans);
70     for(int i=1;i<=cnt;i++)
71         if(v[i]==e)
72             sum=(sum+ans.a[1][i])%mod;
73     printf("%d",sum%mod);
74 }
BZOJ 1875

(PS:矩阵乘法不满足交换律)

posted @ 2017-07-13 18:38  avancent  阅读(139)  评论(0编辑  收藏  举报