ZOJ 3772 Calculate the Function(矩阵线段树)

原创 2015年07月06日 19:51:34

Description

You are given a list of numbers A1A2 .. AN and M queries. For the i-th query:

  • The query has two parameters Li and Ri.
  • The query will define a function Fi(x) on the domain [Li, Ri] ∈ Z.
  • Fi(Li) = ALi
  • Fi(Li + 1) = A(Li + 1)
  • for all x >= Li + 2Fi(x) = Fi(x - 1) + Fi(x - 2) × Ax

You task is to calculate Fi(Ri) for each query. Because the answer can be very large, you should output the remainder of the answer divided by 1000000007.

Input

There are multiple test cases. The first line of input is an integer T indicates the number of test cases. For each test case:

The first line contains two integers NM (1 <= NM <= 100000). The second line contains N integers A1A2 .. AN (1 <= Ai <= 1000000000).

The next M lines, each line is a query with two integer parameters LiRi (1 <= Li <= Ri <= N).

Output

For each test case, output the remainder of the answer divided by 1000000007.

Sample Input

1
4 7
1 2 3 4
1 1
1 2
1 3
1 4
2 4
3 4
4 4

Sample Output

1
2
5
13
11
4
4

题意:给你一段序列,每次问你一段区间构造的数列的最后一项。

分析:这题显然不能暴力,正确做法就是将矩阵套到线段树里,每个节点

里存的都是一个矩阵,然后求区间pushup时候利用矩阵乘法乘一次就行了

注意矩阵相乘的顺序。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<string>
#include<iostream>
#include<queue>
#include<cmath>
#include<map>
#include<stack>
#include<set>
using namespace std;
#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define CLEAR( a , x ) memset ( a , x , sizeof a )
const int INF=0x3f3f3f3f;
typedef long long LL;
const int mod=1e9+7;
const int maxn=1e5+100;
LL a[maxn];
int t,n,m;
struct Matrix{
    LL mat[2][2];
    Matrix(){};
    Matrix(int x)
    {
        mat[0][0]=mat[1][0]=1;
        mat[0][1]=x;mat[1][1]=0;
    }
}A[maxn<<2];
Matrix mult(Matrix m1,Matrix m2)
{
    Matrix ans;
    for(int i=0;i<2;i++)
    {
        for(int j=0;j<2;j++)
        {
            ans.mat[i][j]=0;
            for(int k=0;k<2;k++)
                ans.mat[i][j]=(ans.mat[i][j]+m1.mat[i][k]*m2.mat[k][j])%mod;
        }
    }
    return ans;
}
void build(int rs,int l,int r)
{
    if(l==r)
    {
        A[rs]=Matrix(a[l]);
        return ;
    }
    int mid=(l+r)>>1;
    build(rs<<1,l,mid);
    build(rs<<1|1,mid+1,r);
    A[rs]=mult(A[rs<<1|1],A[rs<<1]);
}
Matrix query(int x,int y,int l,int r,int rs)
{
    if(l>=x&&r<=y)
        return A[rs];
    int mid=(l+r)>>1;
    if(y<=mid) return query(x,y,l,mid,rs<<1);
    if(x>mid) return query(x,y,mid+1,r,rs<<1|1);
    return mult(query(mid+1,y,mid+1,r,rs<<1|1),query(x,mid,l,mid,rs<<1));
}
int main()
{
    int l,r;
    scanf("%d",&t);
    while(t--)
    {
        Matrix hehe;
        scanf("%d%d",&n,&m);
        REPF(i,1,n)
          scanf("%lld",&a[i]);
        build(1,1,n);
        while(m--)
        {
            scanf("%d%d",&l,&r);
            if(r-l<=1)
                printf("%lld\n",a[r]);
            else
            {
                hehe=query(l+2,r,1,n,1);
                LL ans=(hehe.mat[0][0]*a[l+1]%mod+hehe.mat[0][1]*a[l]%mod)%mod;
                printf("%lld\n",ans);
            }
        }
    }
    return 0;
}


zoj3772--【水题】线段树区间查询+矩阵乘法

思路来源:http://blog.csdn.net/u013654696/article/details/23037407#comments 【思路不是自己的,但代码是自己敲的,由于伦家不懂】...
  • u011652573
  • u011652573
  • 2014年04月08日 21:24
  • 709

[矩阵+线段树] zoj 3772 Calculate the Function

题目链接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5235 Calculate the Function ...
  • cc_again
  • cc_again
  • 2014年05月17日 20:48
  • 782

ZOJ 3772 Calculate the Function(线段树+矩阵)

ZOJ 3772 Calculate the Function(线段树+矩阵)
  • u013790563
  • u013790563
  • 2015年05月11日 16:49
  • 587

zoj 3772 Calculate the Function 线段树+矩阵

Time Limit: 2 Seconds Memory Limit: 65536 KB You are given a list of numbers A1 A2 .. AN and M quer...
  • u013287817
  • u013287817
  • 2014年04月07日 18:44
  • 403

zoj 3772 Calculate the Function(矩阵+线段树)

开始以为是数学递推找规律,尝试了以后发现这条路走不通。 考虑到既有加又有乘,可能就是我们熟悉的矩阵。然后想试着用逆矩阵的形式求解,发现会出现a[x] 为分母的情况。所以最后使用线段树来求解区间的矩阵...
  • u011561033
  • u011561033
  • 2015年03月09日 21:12
  • 521

线段树 + 矩阵 --- ZOJ 3772 Calculate the Function

Calculate the Function Problem's Link:   http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCo...
  • u013371163
  • u013371163
  • 2017年03月05日 17:16
  • 75

ZOJ 3772 Calculate the Function (线段树 + 矩阵)

思路分析: 遗憾不知道矩阵的构造。线段树上比较水的矩阵。。。  M[x]  =  [1 A[x]]               [1   0 ]   就有 [  F[R]...
  • u010709592
  • u010709592
  • 2014年05月11日 23:15
  • 814

ZOJ 3772 Calculate the Function(线段树 + 矩阵)

题目链接:ZOJ 3772 Calculate the Function 线段树 + 矩阵。
  • fobdddf
  • fobdddf
  • 2014年04月07日 21:03
  • 980

ZOJ 3772 Calculate the Function( 线段树 )

题意: 给一个序列An 有m个询问,每个询问包括l和r
  • u013654696
  • u013654696
  • 2014年04月06日 18:53
  • 1212

ZOJ 3772 Calculate the Function(线段树)

给出一个序列,并且给出一特递推式,有n次查询每次查询输出递推式的结果。 我们将递推式化简为矩阵,在线段树的节点里存矩阵,每次查询区间的矩阵的乘 #include #include...
  • pootree
  • pootree
  • 2016年04月03日 14:54
  • 169
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:ZOJ 3772 Calculate the Function(矩阵线段树)
举报原因:
原因补充:

(最多只允许输入30个字)