http://acm.sdut.edu.cn:8080/vjudge/contest/view.action?cid=216#problem/X
给出一个序列,在区间[l,r]内定义一个函数f(x),其中f(l) = a[l],f(r) = a[r],f(x) = f(x-1) + f(x-2)*a[x](x >= l+2)。
对于每一个询问区间[l,r],输出f(r)。
刚看到这个题没有什么思路,看到别人的博客标题写着线段树+矩阵,想到f(x)的表达式类似于求斐波那契,于是想到构造矩阵,对于区间[l,r],f[r]可由矩阵乘法求出,所以可以用线段树维护区间[l+2,r]的矩阵的乘积。
#include <stdio.h>
#include <iostream>
#include <map>
#include <set>
#include <list>
#include <stack>
#include <vector>
#include <math.h>
#include <string.h>
#include <queue>
#include <string>
#include <stdlib.h>
#include <algorithm>
#define LL long long
#define eps 1e-12
#define PI acos(-1.0)
#define PP pair<LL,LL>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 100010;
const int mod = 1000000007;
typedef struct matrix
{
LL mat[2][2];
}Matrix;
Matrix operator * (Matrix a, Matrix b)
{
Matrix res;
res.mat[0][0] = res.mat[0][1] = res.mat[1][0] = res.mat[1][1] = 0;
for(int i = 0; i < 2; i++)
{
for(int k = 0; k < 2; k++)
{
if(a.mat[i][k] == 0) continue;
for(int j = 0; j < 2; j++)
{
res.mat[i][j] += a.mat[i][k]*b.mat[k][j]%mod;
res.mat[i][j] %= mod;
}
}
}
return res;
}
struct node
{
int l,r;
Matrix matrix;
}tree[maxn*4];
LL a[maxn];
void push_up(int v)
{
tree[v].matrix = tree[v*2+1].matrix * tree[v*2].matrix;
}
void build(int v, int l, int r)
{
tree[v].l = l;
tree[v].r = r;
if(l == r)
{
Matrix tmp;
tmp.mat[0][0] = (LL)1;
tmp.mat[0][1] = a[l];
tmp.mat[1][0] = (LL)1;
tmp.mat[1][1] = 0;
tree[v].matrix = tmp;
return;
}
int mid = (tree[v].l + tree[v].r)>>1;
build(v*2,l,mid);
build(v*2+1,mid+1,r);
push_up(v);
}
Matrix query(int v, int l, int r)
{
if(tree[v].l == l && tree[v].r == r)
return tree[v].matrix;
int mid = (tree[v].l + tree[v].r) >> 1;
if(r <= mid)
return query(v*2,l,r);
else if(l > mid)
return query(v*2+1,l,r);
else
{
Matrix tmp = query(v*2+1,mid+1,r) * query(v*2,l,mid); //注意顺序
return tmp;
}
}
int main()
{
int test;
int n,m,l,r;
LL ans;
scanf("%d",&test);
while(test--)
{
scanf("%d %d",&n,&m);
for(int i = 1; i <= n; i++)
scanf("%lld",&a[i]);
build(1,1,n);
while(m--)
{
scanf("%d %d",&l,&r);
if(l == r)
printf("%lld\n",a[l]%mod);
else if(r == l+1)
printf("%lld\n",a[r]%mod);
else
{
Matrix tmp = query(1,l+2,r);
ans = (tmp.mat[0][0]*a[l+1]%mod + tmp.mat[0][1]*a[l]%mod)%mod;
printf("%lld\n",ans);
}
}
}
return 0;
}