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


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

    啊呸,是基础数学

    斐波那契的矩阵就不讲了

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

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

    然后又因为 ( exttt{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] << '
    ' ;
    		}
    	}
    	return out.flush(), 0;
    }
    
  • 相关阅读:
    自动化测试全聚合
    选择排序(JAVA实现)
    插入排序(JAVA实现)
    冒泡排序(JAVA实现)
    快速排序(java实现)
    Python+页面元素高亮源码实例
    (原创)Python 自动化测试框架详解
    Python+requests库 POST接口图片上传
    基于Python + requests 的web接口自动化测试框架
    python 创建mysql数据库
  • 原文地址:https://www.cnblogs.com/Isaunoya/p/12233333.html
Copyright © 2020-2023  润新知