HDU 5607 矩阵快速幂

HDU 5607
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5607
题意:
给一个n个点有向图(<=50),有m条边(<=1000).
现在已知对于一个点,下次可以等可能的走到有出边的下一个点。
从一个点出发,求最后走到某个点的概率x/y.输出x * y^(1e9+5)
思路:
妥妥的用矩阵快速幂优化一个转移矩阵没什么好说的。
自己写的时候刚开始写了一发double爆了精度,然后分数类爆了时间。
最后看别人题解发现x * y^(1e9+5)是可以看成乘上y的逆元,然后这题就解决了。
源码:
写残版(但是AC了)

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>
#include <utility>
using namespace std;
#define mod (1000000007)
#define LL long long
const int MAXN = 50 + 5;
LL gcd(LL a, LL b){return b == 0 ? a : gcd(b, a % b);}
struct Matrix
{
    LL a[MAXN][MAXN];
    int num;
    void init(int _num)
    {
        num = _num;
        for(int i = 1 ; i <= num ; i++){
            for(int j = 1 ; j <= num ; j++) a[i][j] = 0;
            a[i][i] = 1;
        }
    }
    void print()
    {
        for(int i = 1 ; i <= num ; i++){
            for(int j = 1 ; j <= num ; j++) printf("%10I64d ", a[i][j]);
            printf("\n");
        }
    }
    Matrix operator * ( Matrix &rbs)const{
        Matrix ans;
        ans.init(num);
        for(int i = 1 ; i <= num ; i++) ans.a[i][i] = 0;
//        printf("\nans\n");
//        ans.print();
//        printf("\nnow\n");
//        for(int i = 1 ; i <= num ; i++){
//            for(int j = 1 ; j <= num ; j++) printf("%10I64d ", a[i][j]);
//            printf("\n");
//        }
//        printf("\nrbs\n");
//        rbs.print();
        for(int i = 1 ; i <= num ; i++){
            for(int k = 1 ; k <= num ; k++){
                for(int j = 1 ; j <= num ; j++){
                    ans.a[i][j] = (ans.a[i][j] + a[i][k] * rbs.a[k][j] % mod) % mod;
//                    if(i == 1 && j == 1){
//                        printf("i = %d, j = %d, k = %d, a[i][k] = %I64d, a[j][k] = %I64d\n", i, j, k, a[i][k], rbs.a[k][j]);
//                    }
                }
            }
        }
//        printf("\nans\n");
//        ans.print();
//        printf("\n");
        return ans;
    }
}org, cur;
Matrix ppow(Matrix a, int v)
{
    Matrix ans;
    ans.init(a.num);
    while(v){
        if(v & 1)   ans = ans * a;
        a = a * a;
        v >>= 1;
    }
    return ans;
}
LL ppow(LL a, int v)
{
    LL ans = 1;
    while(v){
        if(v & 1)   ans = (ans * a) % mod;
        a = (a * a) % mod;
        v >>= 1;
    }
    return ans;
}
LL rev(LL a){return ppow(a, mod - 2);}
vector<int>lin[MAXN];
int n;
int outdegree[MAXN];
int main()
{
//    freopen("HDU 5607.in", "r", stdin);
    int m;
    while(scanf("%d%d", &n, &m) != EOF){
        for(int i = 1 ; i <= n ; i++)   lin[i].clear(), outdegree[i] = 0;
        int u, v;
        for(int i = 0 ; i < m ; i++){
            scanf("%d%d", &u, &v);
            outdegree[u]++;
            lin[v].push_back(u);
        }

        ///init_matrix
        org.num = n;
        for(int i = 1 ; i <= n ; i++)   for(int j = 1 ; j <= n ; j++) org.a[i][j] = 0;
        for(int i = 1 ; i <= n ; i++){
            for(int j = 0 ; j < (int)lin[i].size() ; j++){
                org.a[i][lin[i][j]] = rev(outdegree[lin[i][j]]);
            }
        }
        int q;
        scanf("%d", &q);
        while(q--){
            scanf("%d%d", &u, &v);
//            printf("\norg\n");
//            org.print();
            cur = ppow(org, v);
//            printf("\ncur\n");
//            cur.print();
            for(int i = 1 ; i <= n ; i++)   printf("%I64d ", cur.a[i][u]);
            printf("\n");
        }
    }
    return 0;
}
分数类版(但是TLE)
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>
#include <utility>
using namespace std;
#define mod (1000000007)
#define LL long long
const int MAXN = 50 + 5;
LL gcd(LL a, LL b){return b == 0 ? a : gcd(b, a % b);}
struct Fraction
{
    LL a, b;
    Fraction(){}
    Fraction(LL _a, LL _b){a = _a, b = _b;}
    Fraction operator + (const Fraction &rbs)const{
        Fraction ans;
//        printf("%I64d %I64d, %I64d %I64d\n", a, b, rbs.a, rbs.b);
        ans.b = rbs.b * b / gcd(rbs.b, b);
        ans.a = a * (ans.b / b) + rbs.a * (ans.b / rbs.b);
        ans.a %= mod;
        ans.b %= mod;
        return ans;
    }
    Fraction operator * (const Fraction &rbs)const{
        Fraction ans;
        ans.a = a * rbs.a;
        ans.b = b * rbs.b;
        LL temp = gcd(ans.a, ans.b);
        if(temp){
            ans.a = ans.a / temp;
            ans.b = ans.b / temp;
            ans.a %= mod;
            ans.b %= mod;
        }
//        printf("in * %I64d %I64d, %I64d %I64d, %I64d %I64d\n", a, b, rbs.a, rbs.b, ans.a, ans.b);
        return ans;
    }
};
struct Matrix
{
    Fraction a[MAXN][MAXN];
    int num;
    void init(int _num)
    {
        num = _num;
        for(int i = 1 ; i <= num ; i++){
            for(int j = 1 ; j <= num ; j++) a[i][j] = Fraction(0, 1);
            a[i][i] = Fraction(1, 1);
        }
    }
    Matrix operator * (const Matrix &rbs)const{
        Matrix ans;
        ans.num = rbs.num;
        for(int i = 1 ; i <= num ; i++) for(int j = 1 ; j <= num ; j++) ans.a[i][j] = Fraction(0, 1);
        for(int i = 1 ; i <= num ; i++){
            for(int k = 1 ; k <= num ; k++){
                for(int j = 1 ; j <= num ; j++){
                    ans.a[i][j] = (ans.a[i][j] + a[i][k] * rbs.a[k][j]);
//                    printf("i = %d, j = %d, k = %d, a[i][k] = %I64d %I64d, rbs.a[k][j] = %I64d %I64d, ans.a[i][j] = %I64d %I64d\n", i, j, k, a[i][k].a, a[i][k].b, rbs.a[k][j].a, rbs.a[k][j].b, ans.a[i][j].a, ans.a[i][j].b);
                }
//                printf("ans.a[%d][%d] = %I64d %I64d\n", i, j, ans.a[i][j].a, ans.a[i][j].b);
            }
        }
        return ans;
    }
}org, cur;
Matrix ppow(Matrix a, int v)
{
//    printf("a.num = %d\n", a.num);
    Matrix ans;
    ans.init(a.num);
    while(v){
        if(v & 1)   ans = ans * a;
        a = a * a;
        v >>= 1;
    }
//    printf("a.num = %d, ans.num = %d\n", a.num, ans.num);
    return ans;
}
LL ppow(LL a, int v)
{
    LL ans = 1;
    while(v){
        if(v & 1)   ans = (ans * a) % mod;
        a = (a * a) % mod;
        v >>= 1;
    }
    return ans;
}
vector<int>lin[MAXN];
int n;
int outdegree[MAXN];
LL ansx[MAXN], ansy[MAXN];
void print(Matrix u)
{
    for(int i = 1 ; i <= u.num ; i++){
        for(int j = 1 ; j <= u.num ; j++)   printf("%I64d/%I64d ", u.a[i][j].a, u.a[i][j].b);
        printf("\n");
    }
}
int main()
{
//    freopen("HDU 5607.in", "r", stdin);
    int m;
    while(scanf("%d%d", &n, &m) != EOF){
        for(int i = 1 ; i <= n ; i++)   lin[i].clear(), outdegree[i] = 0;
        int u, v;
        for(int i = 0 ; i < m ; i++){
            scanf("%d%d", &u, &v);
            outdegree[u]++;
            lin[v].push_back(u);
        }

        ///init_matrix
        org.num = n;
        for(int i = 1 ; i <= n ; i++)   for(int j = 1 ; j <= n ; j++) org.a[i][j] = Fraction(0, 1);
        for(int i = 1 ; i <= n ; i++){
            for(int j = 0 ; j < (int)lin[i].size() ; j++){
                org.a[i][lin[i][j]] = Fraction(1, outdegree[lin[i][j]]);
            }
        }
//        printf("first\n");
        int q;
        scanf("%d", &q);
        while(q--){
            scanf("%d%d", &u, &v);
//            Matrix torg = org;
            cur = ppow(org, v);
//            printf("first\n");
//            print(cur);
//            printf("\n");
//            printf("second\n");
//            print(org);
//            org = torg;
            for(int i = 1 ; i <= n ; i++){
                printf("%I64d", cur.a[i][u].a * ppow(cur.a[i][u].b, 1000000005) % mod);
//                printf(" cur.a[i][u] = %I64d %I64d\n", cur.a[i][u].a, cur.a[i][u].b);
//                if(i == n)  printf("\n");
//                else    printf(" ");
                printf(" ");
            }
            printf("\n");
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值