HDU 2254 奥运(矩阵快速幂+二分等比序列求和)

HDU 2254 奥运(矩阵快速幂+二分等比序列求和)

ACM

题目地址:HDU 2254 奥运

题意:

中问题不解释。

分析:

根据floyd的算法,矩阵的k次方表示这个矩阵走了k步。

所以k天后就算矩阵的k次方。

这样就变成:初始矩阵的^[t1,t2]这个区间内的v[v1][v2]的和。

所以就是二分等比序列求和上场的时候了。

HDU 1588 Gauss Fibonacci的算法一样。

代码:

/*
*  Author:      illuz <iilluzen[at]gmail.com>
*  Blog:        http://blog.csdn.net/hcbbt
*  File:        2254.cpp
*  Create Date: 2014-08-04 10:52:29
*  Descripton:  matrix, floyd
*/

#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <algorithm>
using namespace std;
#define repf(i,a,b) for(int i=(a);i<=(b);i++)
typedef long long ll;

const int N = 20;
const int SIZE = 32;        // max size of the matrix
const int MOD = 2008;

int n, k, p1, p2;
ll v1, v2, t1, t2;
map<int, int> mp;

struct Mat{
    int n;
    ll v[SIZE][SIZE];    // value of matrix

    Mat(int _n = SIZE) {
        n = _n;
    }

    void init(ll _v = 0) {
        memset(v, 0, sizeof(v));
        if (_v)
            repf (i, 0, n - 1)
                v[i][i] = _v;
    }

    void output() {
        repf (i, 0, n - 1) {
            repf (j, 0, n - 1)
                printf("%lld ", v[i][j]);
            puts("");
        }
        puts("");
    }
} a, b;

Mat operator * (Mat a, Mat b) {
    Mat c(a.n);
    repf (i, 0, a.n - 1) {
        repf (j, 0, a.n - 1) {
            c.v[i][j] = 0;
            repf (k, 0, a.n - 1) {
                c.v[i][j] += (a.v[i][k] * b.v[k][j]) % MOD;
                c.v[i][j] %= MOD;
            }
        }
    }
    return c;
}

Mat operator ^ (Mat a, ll k) {
    Mat c(a.n);
    c.init(1);
    while (k) {
        if (k&1) c = a * c;
        a = a * a;
        k >>= 1;
    }
    return c;
}

Mat operator + (Mat a, Mat b) {
    Mat c(a.n);
    repf (i, 0, a.n - 1)
        repf (j, 0, a.n - 1)
            c.v[i][j] = (b.v[i][j] + a.v[i][j]) % MOD;
    return c;
}

Mat operator + (Mat a, ll b) {
    Mat c = a;
    repf (i, 0, a.n - 1)
        c.v[i][i] = (a.v[i][i] + b) % MOD;
    return c;
}

Mat calc(Mat a, int n) {
    if (n == 1)
        return a;
    if (n&1)
        return (a^n) + calc(a, n - 1);
    else
        return calc(a, n/2) * ((a^(n/2)) + 1);
}

int main() {
    while (~scanf("%d", &n)) {
        a.init();
        mp.clear();
        int cnt = 0;
        while (n--) {
            scanf("%d%d", &p1, &p2);
            if (mp.find(p1) == mp.end())
                p1 = mp[p1] = cnt++;
            else
                p1 = mp[p1];
            if (mp.find(p2) == mp.end())
                p2 = mp[p2] = cnt++;
            else
                p2 = mp[p2];
            a.v[p1][p2]++;
        }
        a.n = cnt;

        scanf("%d", &k);
        while (k--) {
            scanf("%lld%lld%lld%lld", &v1, &v2, &t1, &t2);
            if (mp.find(v1) == mp.end() || mp.find(v2) == mp.end()) {
                puts("0");
                continue;
            }
            v1 = mp[v1];
            v2 = mp[v2];
            if (t1 > t2)
                swap(t1, t2);
            if (t1 == 0) {
                if (t2 == 0)
                    puts("0");
                else
                    printf("%lld\n", calc(a, t2).v[v1][v2]);
            }
            else if (t1 == 1)
                printf("%lld\n", calc(a, t2).v[v1][v2]);
            else {
                printf("%lld\n", ((calc(a, t2).v[v1][v2] - calc(a, t1 - 1).v[v1][v2]) + MOD) % MOD);
            }
        }
    }
    return 0;
}

HDU 2254 奥运(矩阵快速幂+二分等比序列求和)

时间: 2024-10-12 12:04:35

HDU 2254 奥运(矩阵快速幂+二分等比序列求和)的相关文章

HDU 1588 Gauss Fibonacci(矩阵快速幂+二分等比序列求和)

HDU 1588 Gauss Fibonacci(矩阵快速幂+二分等比序列求和) ACM 题目地址:HDU 1588 Gauss Fibonacci 题意: g(i)=k*i+b;i为变量. 给出k,b,n,M,问( f(g(0)) + f(g(1)) + ... + f(g(n)) ) % M的值. 分析: 把斐波那契的矩阵带进去,会发现这个是个等比序列. 推倒: S(g(i)) = F(b) + F(b+k) + F(b+2k) + .... + F(b+nk) // 设 A = {1,1,

HDU 1588 Gauss Fibonacci(矩阵高速幂+二分等比序列求和)

HDU 1588 Gauss Fibonacci(矩阵高速幂+二分等比序列求和) ACM 题目地址:HDU 1588 Gauss Fibonacci 题意: g(i)=k*i+b;i为变量. 给出k,b,n,M,问( f(g(0)) + f(g(1)) + ... + f(g(n)) ) % M的值. 分析: 把斐波那契的矩阵带进去,会发现这个是个等比序列. 推倒: S(g(i)) = F(b) + F(b+k) + F(b+2k) + .... + F(b+nk) // 设 A = {1,1,

HDU - 1588 Gauss Fibonacci (矩阵快速幂+二分求等比数列和)

Description Without expecting, Angel replied quickly.She says: "I'v heard that you'r a very clever boy. So if you wanna me be your GF, you should solve the problem called GF~. " How good an opportunity that Gardon can not give up! The "Prob

POJ 3233 - Matrix Power Series ( 矩阵快速幂 + 二分)

POJ 3233 - Matrix Power Series ( 矩阵快速幂 + 二分) #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long LL; #define MAX_SIZE 30 #define CLR( a, b ) memset( a, b, sizeof(a) ) int MOD = 0; int n, k; st

Hdu 4965(矩阵快速幂)

题目链接 Fast Matrix Calculation Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 87    Accepted Submission(s): 39 Problem Description One day, Alice and Bob felt bored again, Bob knows Alice is a

HDU 4549 (费马小定理+矩阵快速幂+二分快速幂)

M斐波那契数列 Time Limit: 1000MS   Memory Limit: 32768KB   64bit IO Format: %I64d & %I64u Submit Status Description M斐波那契数列F[n]是一种整数数列,它的定义如下: F[0] = a F[1] = b F[n] = F[n-1] * F[n-2] ( n > 1 ) 现在给出a, b, n,你能求出F[n]的值吗? Input 输入包含多组测试数据: 每组数据占一行,包含3个整数a,

hdu1588 Gauss Fibonacci(矩阵快速幂+二分求矩阵等比和)

题目: Gauss Fibonacci Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2858    Accepted Submission(s): 1186 Problem Description Without expecting, Angel replied quickly.She says: "I'v heard that y

POJ 3233 Matrix Power Series 矩阵快速幂+二分求和

矩阵快速幂,请参照模板 http://www.cnblogs.com/pach/p/5978475.html 直接sum=A+A2+A3...+Ak这样累加肯定会超时,但是 sum=A+A2+...+Ak/2+A(k/2)*(A+A2+...+Ak/2)    k为偶数时: sum=A+A2+...+A(k-1)/2+A((k-1)/2)*(A+A2+...+A(k-1)/2)+Ak    k为奇数时. 然后递归二分求和 PS:刚开始mat定义的是__int64,于是贡献了n次TLE... #i

POJ3233:Matrix Power Series(矩阵快速幂+二分)

http://poj.org/problem?id=3233 题目大意:给定矩阵A,求A + A^2 + A^3 + … + A^k的结果(两个矩阵相加就是对应位置分别相加).输出的数据mod m.k<=10^9.这道题两次二分,相当经典.首先我们知道,A^i可以二分求出.然后我们需要对整个题目的数据规模k进行二分.比如,当k=6时,有:A + A^2 + A^3 + A^4 + A^5 + A^6 =(A + A^2 + A^3) + A^3*(A + A^2 + A^3)应用这个式子后,规模