HDU 2254

http://acm.hdu.edu.cn/showproblem.php?pid=2254

矩阵乘法两个经典问题的综合题,还要离散化和处理边界,好题啊好题

题意容易理解错,每一天是独立的,所以根据加法原理方案数是G^1+G^2+...+G^t

/*

此题要求 (G^1+G^2+...+G^t2)-(G^1+G^2+...+G^(t1-1)) 

求和的方法是再次二分,k=6时 

G + G^2 + G^3 + G^4 + G^5 + G^6 = G + G^2 + G^3 + G^3 * (G + G^2 + G^3) = (1 + G^3) * (G + G^2 + G^3) 

这样计算可以使k的规模减少一半,快速幂求出G^3后可递归计算G+G^2+G^3,即得答案 

*/

#include <iostream> 

#include <cstdio>

#include <cstring>

#include <map>



using namespace std;



#define MOD 2008



#define Mat 35 //矩阵大小

  

struct mat{//矩阵结构体,a表示内容,r行c列 矩阵从1开始  

    int a[Mat][Mat];

    int r, c;  

    mat() {  

        r = c = 0;  

        memset(a, 0, sizeof(a));  

    }  

};  



void print(mat m) {  

    //printf("%d\n", m.size);  

    for(int i = 0; i < m.r; i++) {  

        for(int j = 0; j < m.c; j++) printf("%d ", m.a[i][j]);  

        putchar('\n');  

    }  

}  

  

mat mul(mat m1, mat m2, int mod) {  

    mat ans  = mat();

    ans.r = m1.r, ans.c = m2.c;  

    for(int i = 1; i <= m1.r; i++)  

        for(int j = 1; j <= m2.r; j++)  

            if(m1.a[i][j])

                for(int k = 1; k <= m2.c; k++)  

                    ans.a[i][k] = (ans.a[i][k] + m1.a[i][j] * m2.a[j][k]) % mod;  

    return ans;  

}



mat add(mat m1, mat m2, int mod) {  

    mat ans  = mat();

    ans.r = ans.c = m1.r;  

    for(int i = 1; i <= m1.r; i++)  

        for(int j = 1; j <= m1.r; j++)  

            ans.a[i][j] = (m1.a[i][j] + m2.a[i][j]) % mod;  

    return ans;  

}    



mat quickmul(mat m, int n, int mod) {  

    mat ans = mat();  

    for(int i = 1; i <= m.r; i++) ans.a[i][i] = 1;  

    ans.r = m.r, ans.c = m.c;  

    while(n) {  

        if(n & 1) ans = mul(m, ans, mod);  

        m = mul(m, m, mod);  

        n >>= 1;  

    }  

    return ans;  

}  



mat A;



mat sum(mat m, int n, int mod) {   //m^1+m^2+...+m^n

    if(n == 1) return m;

    if(n & 1) return add(quickmul(m, n, mod), sum(m, n-1, mod), mod);             //是否加m^n 

    else return mul(add(quickmul(m, n>>1, mod), A, mod), sum(m, n>>1, mod), mod); // (1 + m^(n/2)) * (m + m^2 +...+ m^(n/2))

}



/* 

初始化ans矩阵 

mat ans = mat(); 

ans.r = R, ans.c = C;  

ans = quickmul(ans, n, mod); 

*/



int main() {

    A = mat();  

    for(int i = 1; i <= 30; i++) A.a[i][i] = 1;  

    int n;

    while(~scanf("%d", &n)) {

        mat G = mat();

        G.r = G.c = 30;

        map <int, int> mp;

        int rank = 1;

        while(n--) {

            int a, b;

            scanf("%d%d", &a, &b);

            if(!mp[a]) mp[a] = rank++;

            if(!mp[b]) mp[b] = rank++;

            G.a[mp[a]][mp[b]]++;

        }

        int k;

        scanf("%d", &k);

        for(int i = 0; i < k; i++) {

            int v1, v2, t1, t2;

            scanf("%d%d%d%d", &v1, &v2, &t1, &t2);

            v1 = mp[v1];

            v2 = mp[v2];

            if(t1 > t2) swap(t1, t2);

            if(!t1){

                if(!t2) puts("0");

                else {

                    int ans = sum(G, t2, MOD).a[v1][v2];

                    printf("%d\n", ans);

                }

            }

            else if(t1 == 1) {

                int ans = sum(G, t2, MOD).a[v1][v2];

                printf("%d\n", ans);

            }

            else {

                int ans1 = sum(G, t1-1, MOD).a[v1][v2];

                int ans2 = sum(G, t2, MOD).a[v1][v2];

                printf("%d\n", (ans2 - ans1 + MOD) % MOD);

            }

        }

    }

    return 0;

}
View Code

 

你可能感兴趣的:(HDU)