ZOJ3772_Calculate the Function

给出一些数组a[i],每次询问为li,ri,定义f[li]=a[li],f[li+1]=a[li+1],对于其他不超过ri的位置,f[x]=f[x-1]+a[x]*f[x-2] 。

题目有着浓浓的矩阵气息。

f[x]=f[x-1]+a[x]*f[x-2] 

f[x-1]=f[x-1]+0

根据上面两个我们就可以知道

f[x]=========|1,a[x]|         f[x-1]

f[x-1]=======|1 ,  0|         f[x-2]

这样我们就把矩阵构造出来了,相当于每次询问某一段区间的矩阵的乘积。

由于是连续的区间,线段树即可解决问题。

注意矩阵是放在左边,所以大的位置放在左边,线段树操作的时候也需要注意了。

 

 

召唤代码君:

 

 

#include <iostream>
#include <cstring>
#include <cstdio>
#define maxn 300300
#define mod 1000000007
typedef long long ll;
using namespace std;

class Mat{
public:
    ll f[2][2];
    Mat() { f[0][0]=f[1][1]=f[0][1]=f[1][0]=0; }
    Mat(int f1,int f2,int f3,int f4){
        f[0][0]=f1,f[0][1]=f2,f[1][0]=f3,f[1][1]=f4;
    }
    Mat operator * (Mat m1) const{
        Mat m0;
        for (int i=0; i<2; i++)
            for (int j=0; j<2; j++)
                for (int k=0; k<2; k++)
                    m0.f[i][j]=(m0.f[i][j]+f[i][k]*m1.f[k][j])%mod;
        return m0;
    }
    void output(){
        cout<<f[0][0]<<' '<<f[0][1]<<'\n'<<f[1][0]<<' '<<f[1][1]<<'\n';
    }
}tree[maxn];

int n,m,T,a[maxn];

void build(int rt,int l,int r)
{
    if (l==r){
        tree[rt]=Mat(1,a[l],1,0);
        return;
    }
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    tree[rt]=tree[rt<<1|1]*tree[rt<<1];
}

Mat query(int rt,int l,int r,int L,int R)
{
    if (L<=l && R>=r) return tree[rt];
    int mid=(l+r)>>1;
    Mat tot(1,0,0,1);
    if (R> mid) tot=query(rt<<1|1,mid+1,r,L,R);
    if (L<=mid) tot=tot*query(rt<<1,l,mid,L,R);
    return tot;
}

int main()
{
    int x,y;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d%d",&n,&m);
        for (int i=1; i<=n; i++) scanf("%d",&a[i]);
        build(1,1,n);
        while (m--)
        {
            scanf("%d%d",&x,&y);
            if (y==x || y==x+1){
                if (y==x) printf("%d\n",a[x]);
                    else printf("%d\n",a[x+1]);
                continue;
            }
            Mat tmp=query(1,1,n,x+2,y);
            /*
            cout<<" ans Mat is : \n";
            tmp.output();
            cout<<" ...........   the end of Mat.";
            */
            printf("%d\n",(int)((tmp.f[0][0]*a[x+1]+tmp.f[0][1]*a[x])%mod));
        }
    }
    return 0;
}

 

posted @ 2014-07-28 18:03  092000  阅读(1141)  评论(0编辑  收藏  举报