码迷,mamicode.com
首页 > 其他好文 > 详细

CF718C Sasha and Array [线段树+矩阵]

时间:2020-01-25 20:48:03      阅读:110      评论:0      收藏:0      [点我收藏+]

标签:矩阵   char s   The   oid   bool   int   isa   sig   ++i   

我们考虑线性代数上面的矩阵知识

啊呸,是基础数学

斐波那契的矩阵就不讲了

定义矩阵 \(f_x\) 是第 \(x\) 项的斐波那契矩阵

因为
\(f_i * f_j = f_{i+j}\)

然后又因为 \(\texttt{AB+AC=A(B+C)}\)

所以 \(\sum_{i=l}^{r} f(a_i+x) = f(x)\sum_{i=l}^{r} f(a_i)\)

线段树板子题,维护一个矩阵,这题没了

// by Isaunoya
#include <bits/stdc++.h>
using namespace std;

#define rep(i, x, y) for (register int i = (x); i <= (y); ++i)
#define Rep(i, x, y) for (register int i = (x); i >= (y); --i)
#define int long long

const int _ = 1 << 21;
struct I {
    char fin[_], *p1 = fin, *p2 = fin;
    inline char gc() {
        return (p1 == p2) && (p2 = (p1 = fin) + fread(fin, 1, _, stdin), p1 == p2) ? EOF : *p1++;
    }
    inline I& operator>>(int& x) {
        bool sign = 1;
        char c = 0;
        while (c < 48) ((c = gc()) == 45) && (sign = 0);
        x = (c & 15);
        while ((c = gc()) > 47) x = (x << 1) + (x << 3) + (c & 15);
        x = sign ? x : -x;
        return *this;
    }
    inline I& operator>>(double& x) {
        bool sign = 1;
        char c = 0;
        while (c < 48) ((c = gc()) == 45) && (sign = 0);
        x = (c - 48);
        while ((c = gc()) > 47) x = x * 10 + (c - 48);
        if (c == '.') {
            double d = 1.0;
            while ((c = gc()) > 47) d = d * 0.1, x = x + (d * (c - 48));
        }
        x = sign ? x : -x;
        return *this;
    }
    inline I& operator>>(char& x) {
        do
            x = gc();
        while (isspace(x));
        return *this;
    }
    inline I& operator>>(string& s) {
        s = "";
        char c = gc();
        while (isspace(c)) c = gc();
        while (!isspace(c) && c != EOF) s += c, c = gc();
        return *this;
    }
} in;
struct O {
    char st[100], fout[_];
    signed stk = 0, top = 0;
    inline void flush() {
        fwrite(fout, 1, top, stdout), fflush(stdout), top = 0;
    }
    inline O& operator<<(int x) {
        if (top > (1 << 20)) flush();
        if (x < 0) fout[top++] = 45, x = -x;
        do
            st[++stk] = x % 10 ^ 48, x /= 10;
        while (x);
        while (stk) fout[top++] = st[stk--];
        return *this;
    }
    inline O& operator<<(char x) {
        fout[top++] = x;
        return *this;
    }
    inline O& operator<<(string s) {
        if (top > (1 << 20)) flush();
        for (char x : s) fout[top++] = x;
        return *this;
    }
} out;
#define pb emplace_back
#define fir first
#define sec second

template < class T > inline void cmax(T & x , const T & y) {
    (x < y) && (x = y) ;
}
template < class T > inline void cmin(T & x , const T & y) {
    (x > y) && (x = y) ;
}

const int mod = 1e9 + 7 ;
const int maxn = 1e5 + 51 ;
struct matrix {
    int a[3][3] ;
    matrix () {
        rep(i , 1 , 2) rep(j , 1 , 2) a[i][j] = 0 ;
    }
    void clr() {
        rep(i , 1 , 2) rep(j , 1 , 2) a[i][j] = 0 ;
        rep(i , 1 , 2) a[i][i] = 1 ;
    }
    bool empty() {
        if(a[1][1] ^ 1) return false ;
        if(a[1][2] || a[2][1]) return false ;
        if(a[2][2] ^ 1) return false ;
        return true ;
    }
    matrix operator * (const matrix & other) const {
        matrix res ;
        rep(i , 1 , 2) rep(j , 1 , 2) {
            res.a[i][j] = 0 ;
            rep(k , 1 , 2) res.a[i][j] = (res.a[i][j] + a[i][k] * other.a[k][j]) % mod ;
        }
        return res ;
    }
    matrix operator + (const matrix & other) const {
        matrix res ;
        rep(i , 1 , 2) rep(j , 1 , 2) res.a[i][j] = (a[i][j] + other.a[i][j] >= mod) ? a[i][j] + other.a[i][j] - mod : a[i][j] + other.a[i][j] ;
        return res ; 
    }
} ;
matrix qwq ;
matrix qpow(matrix a , int k) {
    matrix res = a ; -- k ;
    for( ; k ; a = a * a , k >>= 1)
        if(k & 1) res = res * a ;
    return res ;
}
int n , m ;
int a[maxn] ;
matrix s[maxn << 2] , tag[maxn << 2] ;
void build(int l , int r , int o) {
    tag[o].clr() ;
    if(l == r) {
        s[o] = qpow(qwq , a[l]) ;
        return ;
    }
    int mid = l + r >> 1 ;
    build(l , mid , o << 1) ;
    build(mid + 1 , r , o << 1 | 1) ;
    s[o] = s[o << 1] + s[o << 1 | 1] ;
}
void psd(int o) {
    if(tag[o].empty()) return ;
    tag[o << 1] = tag[o << 1] * tag[o] ;
    tag[o << 1 | 1] = tag[o << 1 | 1] * tag[o] ;
    s[o << 1] = s[o << 1] * tag[o] ;
    s[o << 1 | 1] = s[o << 1 | 1] * tag[o] ;
    tag[o].clr() ;
}
void upd(int a , int b , int l , int r , matrix x , int o) {
    if(a <= l && r <= b) {
        s[o] = s[o] * x ;
        tag[o] = tag[o] * x ;
        return ;
    }
    psd(o) ;
    int mid = l + r >> 1 ;
    if(a <= mid) upd(a , b , l , mid , x , o << 1) ;
    if(b > mid) upd(a , b , mid + 1 , r , x , o << 1 | 1) ;
    s[o] = s[o << 1] + s[o << 1 | 1] ;
}
matrix qry(int a , int b , int l , int r , int o) {
    if(a <= l && r <= b) {
        return s[o] ;
    } psd(o) ;
    int mid = l + r >> 1 ;
    matrix res ;
    if(a <= mid) res = res + qry(a , b , l , mid , o << 1) ;
    if(b > mid) res = res + qry(a , b , mid + 1 , r , o << 1 | 1) ;
    return res ;
}
signed main() {
#ifdef _WIN64
    freopen("testdata.in" , "r" , stdin) ;
#endif
    qwq.a[1][1] = qwq.a[1][2] = qwq.a[2][1] = 1 ;
    qwq.a[2][2] = 0 ;
    in >> n >> m ;
    rep(i , 1 , n) in >> a[i] ;
    build(1 , n , 1) ;
    while(m --) {
        int opt ;
        in >> opt ;
        if(opt == 1) {
            int l , r , v ;
            in >> l >> r >> v ;
            upd(l , r , 1 , n , qpow(qwq , v) , 1) ;
        }
        else {
            int l , r ;
            in >> l >> r ;
            out << qry(l , r , 1 , n , 1).a[1][2] << '\n' ;
        }
    }
    return out.flush(), 0;
}

CF718C Sasha and Array [线段树+矩阵]

标签:矩阵   char s   The   oid   bool   int   isa   sig   ++i   

原文地址:https://www.cnblogs.com/Isaunoya/p/12233333.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!