HDU 5607 graph(矩阵优化+概率DP)

来源:互联网 发布:淘宝促销手段有哪些 编辑:程序博客网 时间:2024/06/06 01:39

该题很容易想到求概率的转移方程:用d[i][j]表示第i步,走到j点的概率。

但是该题的k高达1e9,所以按照套路,要用矩阵相乘来优化。

第一次写矩阵相乘, 大概的意思就是利用矩阵实现递推, 并且因为每次递推的过程一样, 所以就相当于右乘这个矩阵的k次方。 用矩阵快速幂即可。

矩阵相乘这个问题, 大概可以看成, 矩阵中的每个元素表示到该点的概率, 那么另一个矩阵就是DP矩阵, 表示当前一步到各点的概率, 矩阵相乘就等于下一步到各点的概率(矩阵乘法的意义)。

另外, 要对答案进行1e9+5次方再取模, 如果最后取模, 那么将对分母Y进行取模后再次方再取模, 这是和原问题不等价的, 所以解决方法是按照乘法取模公式, 先对矩阵元素提前处理该操作。

细节参见代码:

#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<string>#include<vector>#include<stack>#include<bitset>#include<cstdlib>#include<cmath>#include<set>#include<list>#include<deque>#include<map>#include<queue>#define Max(a,b) ((a)>(b)?(a):(b))#define Min(a,b) ((a)<(b)?(a):(b))using namespace std;typedef long long ll;const double PI = acos(-1.0);const double eps = 1e-6;const int INF = 1000000000;const int mod = 1000000000 + 7;const int maxn = 1000 + 10;ll T,n,q,u,k,m,x,y,cnt[maxn];vector<ll> g[maxn];typedef vector<ll> vec;typedef vector<vec> mat;mat mul(mat &a, mat &b) {    mat c(a.size(), vec(a.size()));    for(int i=1;i<=n;i++) {        for(int k=1;k<=n;k++) {            for(int j=1;j<=n;j++) {                c[i][j] = (c[i][j] + a[i][k] * b[k][j]) % mod;            }        }    }    return c;}mat pow(mat a, ll k) {    mat b(a.size(), vec(a.size()));    for(int i=1;i<=n;i++) {        b[i][i] = 1;    }    while(k > 0) {        if(k & 1) b = mul(b, a);        a = mul(a, a);        k >>= 1;    }    return b;}ll mod_pow(ll x, ll n, ll mod) {    ll res = 1;    while(n > 0) {        if(n & 1) res = res * x % mod;        x = x * x % mod;        n >>= 1;    }    return res;}int main() {    while(~scanf("%I64d%I64d",&n,&m)) {        for(int i=1;i<=n;i++) g[i].clear();        memset(cnt, 0, sizeof(cnt));        mat a(n+3, vec(n+3));        for(int i=0;i<m;i++) {            scanf("%I64d%I64d",&x,&y);            g[y].push_back(x);            a[y][x] = 1;            cnt[x]++;        }        for(int i=1;i<=n;i++) {            cnt[i] = mod_pow(cnt[i], 1000000005, mod);        }        for(int i=1;i<=n;i++) {            int len = g[i].size();            for(int k=0;k<len;k++) {                a[i][g[i][k]] = (a[i][g[i][k]] * cnt[g[i][k]]) % mod;            }        }        scanf("%I64d",&q);        while(q--) {            scanf("%I64d%I64d",&u,&k);            mat hehe = pow(a, k);            for(int i=1;i<=n;i++) {                printf("%I64d ", hehe[i][u]);            }            printf("\n");        }    }    return 0;}


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 当你嫉妒别人怎么办 单位社保发票丢失怎么办 单位医保发票丢失怎么办 图书明细没有给怎么办 拼音拼不到一起怎么办 孩子不会拼拼音怎么办 小孩子不会拼拼音怎么办 小孩拼音发音不准怎么办 孩子声调不会标怎么办 孩子拼音发音不准怎么办 孩子学拼音不会怎么办? 孩子不会拼生字怎么办? 对数字不敏感怎么办 孩子说话不算数怎么办 儿童做事不认真怎么办 幼儿园小朋友爱打人怎么办 遇到熊孩子家长怎么办 小孩嘴烂了怎么办 孩子杯宠坏了怎么办 小孩子老爱打人怎么办 小孩偏执的性格怎么办 孩子上学爱打人怎么办 宝宝爱动手打人怎么办 幼儿爱打人教师怎么办 中班幼儿爱打人怎么办 幼儿园小班小朋友打人老师怎么办 2岁小朋友打人怎么办 幼儿爱乱讲话怎么办 幼儿园小孩打架老师怎么办 宝宝不自信胆小怎么办 小孩不尊重父母怎么办 孩子有洁癖应该怎么办 宝宝攻击性太弱怎么办 小孩在幼儿园打人怎么办 小孩说老师打人怎么办 孩子总动手打人怎么办 辅导小孩老发火怎么办 孩子喜欢咬人怎么办 小孩见家人不叫怎么办 孩子识字量差怎么办 小孩子字写不好怎么办