hdoj 5607 graph 【矩阵快速幂】
2016-01-02 22:08
183 查看
graphTime Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 103 Accepted Submission(s): 53 Problem Description In a directed graph which has N points and M edges,points are labled from 1 to n.At first I am at point u,at each step I will choose an output edge of the current point at uniform random,for every point Z,please output the possibility of reaching the point Z,moving exactly K steps. Input the first line contains two positive intergesN,M,means the number of points and edges. next M lines,contains two positive intergersX,Y,means an directed edge from X to Y. next line there is an integer Q,means the number of queries. next Q lines,each line contains two integers u,K,means the first point and number of the steps. N≤50,M≤1000,Q≤20,u≤N,K≤109. Every point have at least one output edge. Output Q lines,each line contains N numbers,the i-th number means the possibility of reaching point i from u,moving exactly K steps. In consideration of the precision error,we make some analyses,finding the answer can be represented as the form like XY,you only need to output X×Y109+5 mod (109+7). You need to output an extra space at the end of the line,or you will get PE. Sample Input 3 2 1 2 1 3 1 1 1 Sample Output 0 500000004 500000004 I am now at point $1$,by one move,with a possibity of $\frac{1}{2}$ of reaching point 2,with a possibity of $\frac{1}{2}$ of reaching point 3,so we need to output 0 0.5 0.5,but as what is said above,we need to output$1*2^{10^9+5}~mod~{10^9+7}=500000004$. |
在一个NN个点(标号11~nn),MM条边的有向图上,一开始我在点uu,每一步我会在当前点的出边中等概率的选一条走过去,求走了恰好KK步后走到每个点的概率.
输入描述
第一行两个正整数N,MN,M,表示点数和边数. 接下来MM行,每行两个正整数X,YX,Y.表示一条XX向YY的一条有向边(保证没有重边和自环). 接下来一个正整数QQ,表示询问个数. 接下来QQ行,每行两个正整数u,Ku,K,表示开始的点和步数. N \leq 50, M \leq 1000, Q \leq 20, u \leq n, K \leq 10^{9}N≤50,M≤1000,Q≤20,u≤n,K≤109. 每个点保证至少有一个出边.
输出描述
QQ行,每行NN个数字,用空格隔开,第ii个数字表示从uu开始走KK步到ii的概率. 考虑到输出的答案可能会有精度问题,经过一定的分析后可以发现答案一定可以被表示成\frac{X}{Y}YX的形式,你只需输出X \times Y^{10^9+5} \ mod \ (10^9+7)X×Y109+5 mod (109+7)的值即可. 在每行后面多输出一个空格,否则可能会使你PE.
输入样例
3 2 1 2 1 3 1 1 1
输出样例
0 500000004 500000004
Hint
这是一个三个点,两条边的有向图,它们分别是(1->2,1->3)(1−>2,1−>3).现在在1号点,走了一步后,有1/2的概率走到了2,有1/2的概率走到了3,本来应该输出 0 0.5 0.5 而根据上面所说的,应输出1*2^{10^9+5} \ mod \ (10^9+7)=5000000041∗2109+5 mod (109+7)=500000004.
只能说自己太SB了!!!
思路:设置P[k][i]为第k步到达i点的概率。
那么P[k+1][i] = sigma(P[k][j] * idv(degree[j])) (1 <= j <= N && Map[j][i] == 1)。
求的时候设个逆元就好了,最后结果是一样的。
AC代码:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <algorithm> #include <queue> #include <stack> #include <map> #include <set> #include <vector> #include <string> #define INF 0x3f3f3f3f #define eps 1e-8 #define MAXN (50+10) #define MAXM (500000) #define Ri(a) scanf("%d", &a) #define Rl(a) scanf("%lld", &a) #define Rf(a) scanf("%lf", &a) #define Rs(a) scanf("%s", a) #define Pi(a) printf("%d\n", (a)) #define Pf(a) printf("%.2lf\n", (a)) #define Pl(a) printf("%lld\n", (a)) #define Ps(a) printf("%s\n", (a)) #define W(a) while(a--) #define CLR(a, b) memset(a, (b), sizeof(a)) #define MOD 1000000007 #define LL long long #define lson o<<1, l, mid #define rson o<<1|1, mid+1, r #define ll o<<1 #define rr o<<1|1 #define PI acos(-1.0) using namespace std; struct MATRIX{ struct Matrix{ LL a[MAXN][MAXN]; int r, c; }; Matrix ori, res; Matrix multi(Matrix x, Matrix y) { Matrix z; CLR(z.a, 0); z.r = x.r; z.c = y.c; for(int i = 1; i <= x.r; i++) { for(int k = 1; k <= x.c; k++) { if(x.a[i][k] == 0) continue; for(int j = 1; j <= y.c; j++) z.a[i][j] = (z.a[i][j] + x.a[i][k] * y.a[k][j] % MOD) % MOD; } } return z; } Matrix Pow(Matrix z, int n) { Matrix x; x.r = z.r; x.c = z.c; for(int i = 1; i <= x.r; i++) for(int j = 1; j <= x.c; j++) x.a[i][j] = z.a[i][j]; Matrix y; y.r = y.c = z.r; CLR(y.a, 0); for(int i = 1; i <= y.r; i++) y.a[i][i] = 1; while(n) { if(n & 1) y = multi(y, x); x = multi(x, x); n >>= 1; } return y; } }; MATRIX solve; void exgcd(LL a, LL b, LL &d, LL &x, LL &y) { if(!b) {d = a, x = 1, y = 0;} else { exgcd(b, a%b, d, y, x); y -= x * (a / b); } } LL inv(LL a) { LL d, x, y; exgcd(a, MOD, d, x, y); return (x + MOD) % MOD; } int degree[MAXN]; bool Map[MAXN][MAXN]; int main() { int N, M; while(scanf("%d%d", &N, &M) != EOF) { CLR(degree, 0); CLR(Map, false); for(int i = 0; i < M; i++) { int a, b; Ri(a); Ri(b); Map[a][b] = true; degree[a]++; } for(int i = 1; i <= N; i++) { LL P = inv((LL)degree[i]); for(int j = 1; j <= N; j++) if(Map[i][j]) solve.ori.a[i][j] = P; } solve.ori.r = solve.ori.c = N; int Q; Ri(Q); W(Q) { int u, k; Ri(u); Ri(k); solve.res = solve.Pow(solve.ori, k); for(int i = 1; i <= N; i++) printf("%I64d ", solve.res.a[u][i]); printf("\n"); } } return 0; }
相关文章推荐
- Android中布局的5种模式
- eclipse run andriod程序提示Please ensure that adb is correctly located at 问题
- 购物车角标JSBadgeView的基本使用
- python 代码片段4
- 工厂三兄弟之简单工厂模式(四):改进,简化,总结
- hdoj tree 5606 (并查集)
- squid 透明代理和反向代理
- Windows8.1配置Java环境变量
- 百度地图点击覆盖物,显示信息框js代码
- 聚合函数的使用
- hdoj geometry 5605 (简单数学规律)
- HDU 1083.Courses【二分匹配】【1月2】
- setObject()用法
- 关于service的一点学习笔记
- Centos如何使用SSH远程连接主机
- [转载]UML类图总结
- ClassLoader详解及用途
- C#位运算
- NSURLConection相关知识
- 五.OC基础--1.多态,2.类对象,3.点语法,4.@property&@synthesize,5.动态类型,内省(判断对象是否遵循特定的协议,以及是否可以响应特定的消息)