码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 2254(矩阵快速幂+分治)

时间:2015-06-04 22:50:28      阅读:159      评论:0      收藏:0      [点我收藏+]

标签:

题解:首先要城市要离散化,根据离散数学中可达矩阵的定义,给出一个有向图的邻接矩阵A,res = (A + E)^n表示这个矩阵n步后的可达情况,res[i][j]表示点i经过n步后到点j的方法数,那么给出了t1至t2后从v1到v2的方法数,就是要计算A^t1 + A^(t1 + 1) + … + A^(t2)
用了分治的思想计算,之前有写过模板http://blog.csdn.net/hyczms/article/details/46137531

#include <stdio.h>
#include <string.h>
#include <vector>
const int MOD = 2008;
const int N = 35;
struct Mat {
    int g[N][N];
}reach;
int cnt, k, n;
long long city[N];

Mat multiply(Mat x, Mat y) {
    Mat temp;
    for (int i = 0; i < cnt; i++)
        for (int j = 0; j < cnt; j++) {
            temp.g[i][j] = 0;
            for (int l = 0; l < cnt; l++)
                temp.g[i][j] = (temp.g[i][j] + x.g[i][l] * y.g[l][j]) % MOD;
        }
    return temp;
}

Mat add(Mat x, Mat y) {
    Mat temp;
    for (int i = 0; i < cnt; i++)
        for (int j = 0; j < cnt; j++)
            temp.g[i][j] = (x.g[i][j] + y.g[i][j]) % MOD;
    return temp;
}

Mat power(Mat x, int p) {
    Mat res;
    memset(res.g, 0, sizeof(res.g));
    for (int i = 0; i < cnt; i++)
        res.g[i][i] = 1;    
    while (p) {
        if (p & 1)
            res = multiply(res, x);     
        p >>= 1;
        x = multiply(x, x);
    }
    return res;
}

Mat get_sum(Mat x, int p) {
    if (p == 1)
        return x;
    Mat e;
    memset(e.g, 0, sizeof(e.g));
    for (int i = 0; i < cnt; i++)   
        e.g[i][i] = 1;
    if (p & 1)
        return add(get_sum(x, p - 1), power(x, p));
    return multiply(add(power(x, p >> 1), e), get_sum(x, p >> 1));
}

int Find(long long x) {
    for (int i = 0; i < cnt; i++)
        if (city[i] == x)
            return i;
    return -1;
}

int main() {
    while (scanf("%d", &n) == 1) {
        memset(reach.g, 0, sizeof(reach.g));
        cnt = 0;
        int a, b;
        while (n--) {
            scanf("%d%d", &a, &b);
            int temp1 = Find(a);
            if (temp1 == -1) {
                temp1 = cnt;
                city[cnt++] = a;
            }
            int temp2 = Find(b);
            if (temp2 == -1) {
                temp2 = cnt;
                city[cnt++] = b;
            }
            reach.g[temp1][temp2]++;
        }
        scanf("%d", &k);
        while (k--) {
            long long res;
            int t1, t2, v1, v2;
            scanf("%d%d%d%d", &v1, &v2, &t1, &t2);
            int temp1 = Find(v1);
            int temp2 = Find(v2);
            if (temp1 == -1 || temp2 == -1 || (t1 == 0 && t2 == 0)) {
                printf("0\n");
                continue;
            }
            if (t1 > 1)
                res = (get_sum(reach, t2).g[temp1][temp2] - get_sum(reach, t1 - 1).g[temp1][temp2]) % MOD;
            else
                res = get_sum(reach, t2).g[temp1][temp2] % MOD;
            printf("%lld\n", (res + MOD) % MOD);
        }
    }
    return 0;
}

hdu 2254(矩阵快速幂+分治)

标签:

原文地址:http://blog.csdn.net/hyczms/article/details/46366413

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!