您的位置:首页 > 产品设计 > UI/UE

Hdu 3936 FIB Query[矩阵快速幂](2011 Multi-University Training Contest 10 - Host by HRBEU)

2014-09-26 13:57 721 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3936

题目的意思是,p[i] =F[4 * i - 1],(F为斐波那契数列,F1 = 1,F2 = 1)。。求p[L] ~ p[R]的和。(包括p[L] , p[R])。。。。。每次询问,L,R(L,R均小于10^12)。。。最多询问10^4次。。。

推个公式吧。。。正确的公式是矩阵快速幂的前提。。。所以就开始推了。。。

设Si 为p[1] ~ p[i] 的和。。Si = Si-1 + F(4 *1 - 1)。。。这么容易就出来了。。。毫无违和感啊。。。

那就来推状态转移矩阵吧。。。。

初始状态矩阵。。

(Si-1, F4i - 2, F4i - 3)

A = {

1 0 0

1 1 1

1 1 0

};

转移状态(Si,F4i-1,F4i -2)。。。

好easy。。。很happy的开始写程序。。。各种条,就是不对。。。纳闷了。。。

后来又推了一下 。。。状态方程错了。。。。。。好吧。。

上述公式错误。。LZ你逗我??

后来再推状态转移矩阵。。。

我们发现。。。p的推导对于F是不连续的。。。。每个p相对于F相隔4个。。。那么我们的状态矩阵可以涉及到相邻的每个p。。。也即是相邻的每4个F。。这样说好像比较抽象。。。那就举个例子吧。。

比如第一个状态到第二个状态。。。

(S1,F6,F5,F4,F3)->(S2,F10,F9,F8,F7)

当然这不是唯一的状态转移方式。。。

以上面的例子来推导状态转移矩阵。。。

A = {

1 5 3 2 1

1 3 2 1 1

1 0 0 0 0

0 0 0 0 0

0 0 0 0 0

};

比较有意思。。。当然,不同的转移方式会有不同的状态转移矩阵。。。。

这样就很可以了。。。矩阵快速幂求。。。。。

Code:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
#define LL long long
const int N = 10;
const LL mod = 1000000007;
struct Matrix
{
    int n, m;
    LL a

;
    void CLR(){
        for(int i = 1; i <= n; i ++){
            for(int j = 1; j <= m; j ++)
            a[i][j] = 0;
        }
    }
    void Unit(){
        for(int i = 1; i <= n; i ++){
            a[i][i] = 1;
        }
    }
};

Matrix operator *(Matrix a, Matrix b)
{
    Matrix ans;
    ans.n = a.n; ans.m = b.m;
    ans.CLR();
    for(int i = 1; i <= a.n; i ++){
        for(int k = 1; k <= b.m; k ++){
            if(a.a[i][k])
            for(int j = 1; j <= b.n; j ++)
            ans.a[i][j] = (ans.a[i][j] + a.a[i][k] * b.a[k][j]) % mod;
        }
    }
    return ans;
}

Matrix power(Matrix ans, Matrix A, LL k)
{
    if(k < 0) {
        ans.a[1][1] = 0;
        return ans;
    }
    while(k){
        if(k & 1) ans = ans * A;
        A = A * A;
        k = k >> 1;
    }
    return ans;
}

int main()
{
//    freopen("1.txt", "r", stdin);
//    freopen("2.txt", "w", stdout);
    int q;
    cin >> q;
    Matrix A;
    A.n = 5;A.m = 5;
    A.CLR();
    A.a[1][1] = 1;
    A.a[2][1] = 1; A.a[2][2] = 5;  A.a[2][3] = 3; A.a[2][4] = 2; A.a[2][5] = 1;
    A.a[3][1] = 1; A.a[3][2] = 3;  A.a[3][3] = 2; A.a[3][4] = 1; A.a[3][5] = 1;
    while(q --){
        LL l, r;
        cin >> l >> r;
        Matrix ans;
        ans.n = 1; ans.m = 5;
        ans.CLR();
        ans.a[1][1] = 2; ans.a[1][2] = 8; ans.a[1][3] = 5; ans.a[1][4] = 3; ans.a[1][5] = 2;
        LL xans = power(ans, A, r - 1).a[1][1] - power(ans, A, l - 1 - 1).a[1][1];
        printf("%I64d\n",(xans % mod + mod) % mod); 
    }
    return 0;
}


然后就是被卡了那么一小会儿。。。(一个上午T.T)。。

最后发现。。。。取模那可能为负。。。表示 。。。。无语了那么一会儿。。好吧。。还是自己比较嫩。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐