本文共 2469 字,大约阅读时间需要 8 分钟。
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5235
因为有F(x)*A(x+2) + F(x+1) = F(x+2), 所以构造矩阵
{0 1} { F(x)} {F(x+1)}
{A(x+2) 0}*{ F(x+1)}={ F(x+2)}
用线段树维护乘号左边的矩阵的乘积,注意矩阵相乘的先后顺序,矩阵不符合交换率但符合结合律。
#include#include #include #define ls(x) (x<<1)#define rs(x) ((x<<1)|1)using namespace std;typedef long long ll;const int maxn = 100000+10;const int mod = 1000000007;int a[maxn];struct Mat{ int m[2][2]; void setE() { m[0][0] = m[1][1] = 1; m[0][1] = m[1][0] = 0; } void setZ() { m[0][0] = m[0][1] = m[1][0] = m[1][1] = 0; } void display() { for(int i = 0; i < 2; i++){ for(int j = 0; j < 2; j++) { printf("%d ", m[i][j]); } putchar('\n'); } }};Mat mat[maxn * 8];Mat operator * (const Mat &a, const Mat &b){ Mat ret; ret.setZ(); for(int i = 0; i < 2; i++) for(int j = 0; j < 2; j++) for(int k = 0; k < 2; k++) ret.m[i][j] = ((ll)a.m[i][k]*b.m[k][j] + ret.m[i][j])%mod; return ret;}void Build(int cur, int l, int r){ int m; if(l == r) { mat[cur].m[0][0] = 0; mat[cur].m[0][1] = 1; mat[cur].m[1][0] = a[l]; mat[cur].m[1][1] = 1; }else { m = l + ((r-l)>>1); Build(ls(cur), l, m); Build(rs(cur), m+1, r); mat[cur] = mat[rs(cur)] * mat[ls(cur)]; }}Mat Query(int cur, int l, int r, int ql, int qr){ int m; Mat ret; if(ql <= l && r <= qr) return mat[cur]; else { m = l + ((r-l)>>1); ret.setE(); if(ql <= m) ret = ret * Query(ls(cur), l, m, ql, qr); if(m < qr) ret = Query(rs(cur), m+1, r, ql, qr) * ret; } return ret;}int main(){// freopen("data.in", "r", stdin); int tcas, n, m, l, r; Mat L, R, ret; scanf("%d", &tcas); while(tcas--) { 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", &l, &r); R.m[0][0] = a[l]; R.m[0][1] = 0; R.m[1][0] = a[l+1]; R.m[1][1] = 0; if(r - l >= 2) { L = Query(1, 1, n, l+2, r); ret = L * R; printf("%d\n", ret.m[1][0]); } else { printf("%d\n", a[r]); } } } return 0;}
转载地址:http://qbhrb.baihongyu.com/