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;
}


ZOJ 3772 Calculate the Function [线段树+矩阵乘法]【思维?】

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3772 ————————————————————————————...

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

Calculate the Function Time Limit: 2 Seconds      Memory Limit: 65536 KB You are given a ...

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

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

zoj 3772 Calculate the Function(矩阵乘法)

题意:
  • qian99
  • qian99
  • 2014年04月06日 18:50
  • 715

ZOJ 3772 Calculate the Function(线段树)

给出一个序列,并且给出一特递推式,有n次查询每次查询输出递推式的结果。 我们将递推式化简为矩阵,在线段树的节点里存矩阵,每次查询区间的矩阵的乘 #include #include...
  • pootree
  • pootree
  • 2016年04月03日 14:54
  • 164

zoj3772【线段树+矩阵相乘】

Calculate the FunctionTime Limit: 2 Seconds      Memory Limit: 65536 KB You are given a list of num...

ZOJ 3772 矩阵 + 线段树

传送门 :zoj 3772 题解 还是节点存储矩阵, 不过这题各哥节点基矩阵不同, 所以要考虑方向,wa + 3, pe + 1 AC code:#include #include #includ...
  • ADjky
  • ADjky
  • 2016年12月10日 18:41
  • 157

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

思路来源:http://blog.csdn.net/u013654696/article/details/23037407#comments 【思路不是自己的,但代码是自己敲的,由于伦家不懂】...

zoj 3772 Calculate the Function

Calculate the Function Time Limit: 2 Seconds      Memory Limit: 65536 KB You are given a list ...

ZOJ 3772 线段树

点击打开链接 题意:给一个数字序列,然后有m次询问,每次询问给了一个递推关系,然后输出询问的R的值 思路:n是100000,m是100000,然后来询问,就算不知道题意肯定也要向线段树这方面来想,...
  • Dan__ge
  • Dan__ge
  • 2016年05月23日 20:20
  • 4002
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:ZOJ 3772 Calculate the Function(矩阵线段树)
举报原因:
原因补充:

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