【SDOI2009】【BZOJ1875】HH去散步
2015-08-28 10:29
274 查看
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
Day1
矩乘DP.
根据边的关系建出矩阵然后做快速幂.
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
Day1
矩乘DP.
根据边的关系建出矩阵然后做快速幂.
[code]#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #define MAXN 250 #define P 45989 using namespace std; int n,m,t,A,B; int top=1,size; int ans; struct edge { int from,to,num; edge *next; }e[MAXN<<1],*prev[MAXN]; void insert(int u,int v) { e[++top].to=v;e[top].next=prev[u];prev[u]=&e[top];e[top].num=top;e[top].from=u; } struct matrix { int a[MAXN][MAXN]; matrix() { memset(a,0,sizeof(a)); } friend matrix operator *(matrix A,matrix B) { matrix ret; for (int i=1;i<=size;i++) for (int j=1;j<=size;j++) for (int k=1;k<=size;k++) ret.a[i][j]=(ret.a[i][j]+A.a[i][k]*B.a[k][j])%P; return ret; } friend matrix operator ^(matrix x,int k) { matrix ret; for (int i=1;i<=size;i++) ret.a[i][i]=1; for (int i=k;i;i>>=1,x=x*x) if (i&1) ret=ret*x; return ret; } }st,tmp; int main() { scanf("%d%d%d%d%d",&n,&m,&t,&A,&B); for (int i=1;i<=m;i++) { int u,v; scanf("%d%d",&u,&v); insert(u,v);insert(v,u); } size=top; for (edge *i=prev[A];i;i=i->next) st.a[1][i->num]++; for (int i=2;i<=top;i++) for (int j=2;j<=top;j++) if (e[i].to==e[j].from&&i!=(j^1)) tmp.a[i][j]++; st=st*(tmp^(t-1)); for (edge *i=prev[B];i;i=i->next) ans+=st.a[1][i->num^1]; ans%=P; printf("%d\n",ans); }
相关文章推荐
- java多线程编程--如何开始一个线程
- C# 接口的隐式与显示实现
- Android Fragment——概要介绍
- hdu 5040(2014年北京赛区网络赛)
- LeetCode题解:Remove Duplicates from Sorted List
- 管理两个字
- 使用jsonEditor打造一个复杂json编辑器
- jQuery JCrop插件的使用详解
- 快速排序python实现
- Linux下使用vi命令后退出方式
- 数据结构与算法分析Java版第1章练习1.2
- nyoj1016德莱联盟【判断两线段是否相交】
- 使用Thrift RPC编写程序
- 通过代码快速理解Java代码块
- 8月25日全球域名商(国际域名)解析新增量TOP20
- PostgreSQL与中文社区
- mybatis在xml文件中处理大于号小于号的方法
- 3Sum Closest
- 在Ajax中什么时候用GET什么时候用POST?
- springMVC文件上传