### Codeforces719E 矩陣乘法+線段樹

Codeforces 719E 矩陣乘法+線段樹

1.1 1 r z [l,r] $[l,r]$區間加上一個數 z $z$

2.2 l r 查詢 [l,r] $[l,r]$ 區間內所有的數字，對應在 fib $fib$ 中的值

(fib(i2)fib(i1))(1110)=(fib(i1)fib(i)) $\begin{pmatrix}fib(i-2)&fib(i-1)\\ \end{pmatrix}*\begin{pmatrix} 1&1 \\ 1 & 0\end{pmatrix} =\begin{pmatrix} fib(i-1)&fib(i)\end{pmatrix}$

E(A+B)=EA+EB $E* (A+B) = E* A+E*B$

(A+B)E=AE+BE $(A+B)* E = A* E +B*E$

#include <stdio.h>#include <string.h>#include <algorithm>#include <iostream>const int mod = 1e9+7;typedef long long LL;using namespace std;const int M = 400005;struct Matrix{    int n;    int m;    long long a[3][3];    Matrix () {};    Matrix (int x,int y)    {        n=x;        m=y;        memset(a,0,sizeof(a));    }};Matrix operator+(const Matrix &a,const Matrix &b){    Matrix res (a.n,a.m);    for(int i=0;i<a.n;++i)        for(int j=0;j<b.m;++j)            (res.a[i][j] += a.a[i][j] + b.a[i][j])%=mod;    return res;}Matrix operator*(const Matrix &a,const Matrix &b){    Matrix res (a.n,b.m);    for(int i=0;i<a.n;++i)        for(int j=0;j<b.m;++j)            for(int k=0;k<a.m;++k)                (res.a[i][j] += a.a[i][k] * b.a[k][j])%=mod;        return res;}Matrix pow(Matrix a,LL b){    Matrix res (a.n,a.m);    for(int i=0;i<a.n;++i)        for(int j=0;j<a.m;++j)            res.a[i][j] = (i == j);    for(;b;b>>=1,a=a*a)        if(b&1)            res = res * a;    return res;}struct seg{    Matrix lazy,sum;    bool flag;}tr[M];void init(Matrix &b){    b.n = b.m =2;    for(int i=0;i<b.n;++i)        for(int j=0;j<b.m;++j)            b.a[i][j] = (i == j);}Matrix fib_init_Fir(int x){    Matrix res(2,2);    res.a[0][0] = res.a[1][0] = res.a[0][1] = 1;    return pow(res,x-1);}Matrix fib_init_Sec(int x){    Matrix res(2,2);    res.a[0][0] = res.a[1][0] = res.a[0][1] = 1;    return pow(res,x);}void updata(int k){    tr[k].sum = tr[k<<1].sum + tr[k<<1|1].sum;}void down(int k){    if(tr[k].flag)    {        tr[k<<1].lazy = tr[k].lazy * tr[k<<1].lazy;        tr[k<<1|1].lazy = tr[k].lazy * tr[k<<1|1].lazy;        tr[k<<1].sum = tr[k<<1].sum * tr[k].lazy;        tr[k<<1|1].sum = tr[k<<1|1].sum * tr[k].lazy;        tr[k<<1].flag = tr[k<<1|1].flag = 1;        tr[k].flag = 0; init(tr[k].lazy);    }}inline int read(){    int x = 0, f = 1; char ch = getchar();    while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }    return x * f;}void build(int k,int l,int r){    if(l==r)    {        int x = read();        tr[k].sum = fib_init_Fir(x);        init(tr[k].lazy); tr[k].flag = 0 ;        return ;    }    tr[k].sum = Matrix(2,2); init(tr[k].lazy);tr[k].flag = 0;    int mid = (l+r)>>1;    build(k<<1,l,mid);    build(k<<1|1,mid+1,r);    updata(k);}void change(int k,int l,int r,int x,int y,Matrix tmp){    if(x <= l  && r <= y)    {        tr[k].lazy = tr[k].lazy * tmp;        tr[k].flag = 1;        tr[k].sum = tr[k].sum * tmp;        return ;    }       down(k);    int mid = (l+r)>>1;    if(x <= mid)change(k<<1,l,mid,x,y,tmp);    if(y > mid) change(k<<1|1,mid+1,r,x,y,tmp);    updata(k);}LL ask(int k,int l,int r,int x,int y){    if(x <= l && r <= y) return tr[k].sum.a[0][0];    int mid = (l+r)>>1;    down(k);    LL ans = 0;    if(x <= mid) ans += ask(k<<1,l,mid,x,y);    if(y > mid) ans += ask(k<<1|1,mid+1,r,x,y);    updata(k) ;    return ans % mod;}void out(Matrix &a){    for(int i=0;i<a.n;++i)    {        for(int j=0;j<a.m;++j)            printf("%d ",a.a[i][j]);        puts("");    }}int main(){    int n = read(), m = read();    build(1,1,n);//  out(tr[1].lazy);    while(m--)    {        int op = read(), l = read() , r = read();        if(op == 1)        {            int x = read();            change(1,1,n,l,r,fib_init_Fir(x+1));        }        else printf("%I64d\n",ask(1,1,n,l,r));    }}