传送门 :zoj 3772
题解
还是节点存储矩阵, 不过这题各哥节点基矩阵不同, 所以要考虑方向,wa + 3, pe + 1
AC code:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define mid ((l + r) >> 1)
#define ls rt << 1, l, mid
#define rs rt << 1 | 1, mid + 1, r
typedef long long LL;
const LL MOD = 1000000007;
const LL maxn = 100000 + 5;
int n, M;
struct Matrix{
LL v[2][2];
void clr() {
memset(v, 0, sizeof(v));
}
void E() {
clr();
for (int i = 0; i < 2; ++i) v[i][i] = 1;
}
void init(LL a, LL b, LL c, LL d) {
v[0][0] = a;
v[0][1] = b;
v[1][0] = c;
v[1][1] = d;
}
void debug() {
for (int i = 0; i < 2; ++i)
for (int j = 0; j < 2; ++j)
cout << v[i][j] << (j == 1 ? "\n" : " ");
}
Matrix operator * (Matrix b) {
Matrix res;
res.clr();
for (int i = 0; i < 2; ++i)
for (int j = 0; j < 2; ++j)
for(int k = 0; k < 2; ++k)
res.v[i][j] = (res.v[i][j] + v[i][k] * b.v[k][j]) % MOD;
return res;
}
//Matrix
}a[maxn << 2];
void build() {//zkw线段树
LL x;
for (M = 1; M <= n + 1; M <<= 1);
for (int i = M + 1; i <= M + n; ++i) {
scanf("%I64d", &x);
a[i].init(0, x, 1, 1);
}
for (int i = M - 1; i; --i) {
a[i] = a[i << 1] * a[i << 1 | 1];
}
}
LL query(int l, int r) {
int id = l + M;
l += M + 1;//查询[l + 2, r]的矩阵积, l += M - 1 + 2;
r += M + 1;
Matrix tmp, la, ra;
la.E();
ra.E();
//tmp.E();
while (r ^ l ^ 1) {
if (~l & 1) la = la * a[l + 1];//方向问题, 后来才反应过来
if (r & 1) ra = a[r - 1] * ra;
l >>= 1;
r >>= 1;
}
tmp = la * ra;
LL res = (a[id].v[0][1] * tmp.v[0][1] + a[id + 1].v[0][1] * tmp.v[1][1]) % MOD;
if (res < 0) res += MOD;
return res;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
cin.tie(0);
cin.sync_with_stdio(false);
int T, q, l, r;
scanf("%d", &T);
while (T--) {
for (int i = 1; i < maxn << 2; ++i) a[i].E();
scanf("%d%d", &n, &q);
build();
while (q--) {
scanf("%d%d", &l, &r);
if(r - l >= 2) printf("%d\n", query(l, r));
else printf("%d\n", a[r + M].v[0][1]);
}
}
return 0;
}