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

2014 Super Training #7 E Calculate the Function --矩阵+线段树

时间:2014-07-11 09:03:35      阅读:236      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   strong   os   

原题:ZOJ 3772 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3772

这题算是长见识了,还从没坐过矩阵+线段树的题目呢,不要以为矩阵就一定配合快速幂来解递推式的哦。

由F(x)=F(x-1)+F(x-2)*A[x],转化为矩阵乘法:

bubuko.com,布布扣 ===》bubuko.com,布布扣

所以维护一颗线段树,线段树的每个结点保存一个矩阵,叶子节点为: a[0][0] = a[1][0] = 1, a[0][1] = Ax, a[1][1] = 0的形式

否则保存 a[r] * a[r-1] * ... * a[l] 的结果矩阵,且要注意不要乘反了。

代码:

bubuko.com,布布扣
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#define Mod 1000000007
#define ll long long
using namespace std;
#define N 100007

struct Matrix
{
    ll m[2][2];
    Matrix(int _x)
    {
        m[0][0] = 1;
        m[0][1] = _x;
        m[1][0] = 1;
        m[1][1] = 0;
    }
    Matrix(){}
}tree[4*N];
ll A[N];

Matrix Mul(Matrix a,Matrix b)
{
    Matrix c;
    memset(c.m,0,sizeof(c.m));
    for(int i=0;i<2;i++)
        for(int j=0;j<2;j++)
            for(int k=0;k<2;k++)
                c.m[i][j] = (c.m[i][j] + a.m[i][k]*b.m[k][j])%Mod;
    return c;
}

void build(int l,int r,int rt)
{
    if(l == r)
    {
        tree[rt] = Matrix(A[l]);
        return;
    }
    int mid = (l+r)/2;
    build(l,mid,2*rt);
    build(mid+1,r,2*rt+1);
    tree[rt] = Mul(tree[2*rt+1],tree[2*rt]);  //注意不要乘反了
}

Matrix query(int l,int r,int aa,int bb,int rt)
{
    if(aa<=l && bb>=r)
        return tree[rt];
    int mid = (l+r)/2;
    if(aa>mid)
        return query(mid+1,r,aa,bb,2*rt+1);
    else if(bb<=mid)
        return query(l,mid,aa,bb,2*rt);
    else
        return Mul(query(mid+1,r,aa,bb,2*rt+1),query(l,mid,aa,bb,2*rt)); //不要乘反
}

int main()
{
    int n,m;
    int i,t;
    int aa,bb;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;i++)
            scanf("%lld",&A[i]);
        build(1,n,1);
        while(m--)
        {
            scanf("%d%d",&aa,&bb);
            if(bb-aa<=1)
                printf("%lld\n",A[bb]);
            else
            {
                Matrix ans = query(1,n,aa+2,bb,1);
                ll res = ans.m[0][0]*A[aa+1]%Mod + ans.m[0][1]*A[aa]%Mod;
                printf("%lld\n",res%Mod);
            }
        }
    }
    return 0;
}
View Code

 

2014 Super Training #7 E Calculate the Function --矩阵+线段树,布布扣,bubuko.com

2014 Super Training #7 E Calculate the Function --矩阵+线段树

标签:style   blog   http   color   strong   os   

原文地址:http://www.cnblogs.com/whatbeg/p/3834569.html

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