• CF575A Fibonotci [线段树+矩阵快速幂]


    题意
    (s{}) 是一个循环数列
    循环节为 (n),你可以改掉 (m) 项,这 (m) 项独立,且不影响循环节
    考虑线段树维护矩阵,单点修改最多m次,每次矩阵快速幂就完事了

    // powered by c++11
    // by Isaunoya
    #include<bits/stdc++.h>
    #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)
    using namespace std ;
    using db = double ;
    using ll = long long ;
    using uint = unsigned int ;
    #define int long long
    using pii = pair < int , int > ;
    #define ve vector
    #define Tp template
    #define all(v) v.begin() , v.end()
    #define sz(v) ((int)v.size())
    #define pb emplace_back
    #define fir first
    #define sec second
    // the cmin && cmax
    Tp < class T > void cmax(T & x , const T & y) {
    		if(x < y) x = y ;
    }
    Tp < class T > void cmin(T & x , const T & y) {
    		if(x > y) x = y ;
    }
    // sort , unique , reverse
    Tp < class T > void sort(ve < T > & v) {
    		sort(all(v)) ;
    }
    Tp < class T > void unique(ve < T > & v) {
    		sort(all(v)) ;
    		v.erase(unique(all(v)) , v.end()) ;
    }
    Tp < class T > void reverse(ve < T > & v) {
    		reverse(all(v)) ;
    }
    const int SZ = 0x191981 ;
    struct FILEIN {
    	~ FILEIN () {} char qwq[SZ] , * S = qwq , * T = qwq , ch ;
    	char GETC() {
    		return (S == T) && (T = (S = qwq) + fread(qwq , 1 , SZ , stdin) , S == T) ? EOF : * S ++ ;
    	}
    	FILEIN & operator >> (char & c) {
    		while(isspace(c = GETC())) ;
    		return * this ;
    	}
    	FILEIN & operator >> (string & s) {
    		while(isspace(ch = GETC())) ;
    		s = "" + ch ;
    		while(! isspace(ch = GETC())) s += ch ;
    		return * this ;
    	}
    	Tp < class T > void read(T & x) {
    			bool sign = 1 ;
    			while((ch = GETC()) < 0x30) if(ch == 0x2d) sign = 0 ;
    			x = (ch ^ 0x30) ;
    			while((ch = GETC()) > 0x2f) x = x * 0xa + (ch ^ 0x30) ;
    			x = sign ? x : -x ;
    	}
    	FILEIN & operator >> (int & x) {
    		return read(x) , * this ;
    	}
    	FILEIN & operator >> (signed & x) {
    		return read(x) , * this ;
    	}
    	FILEIN & operator >> (unsigned & x) {
    		return read(x) , * this ;
    	}
    } in ;
    struct FILEOUT {
    	const static int LIMIT = 0x114514 ;
    	char quq[SZ] , ST[0x114] ;
    	signed sz , O ;
    	~ FILEOUT () {
    		sz = O = 0 ;
    	}
    	void flush() {
    		fwrite(quq , 1 , O , stdout) ;
    		fflush(stdout) ;
    		O = 0 ;
    	}
    	FILEOUT & operator << (char c) {
    		return quq[O ++] = c , * this ;
    	}
    	FILEOUT & operator << (string str) {
    		if(O > LIMIT) flush() ;
    		for(char c : str) quq[O ++] = c ;
    		return * this ;
    	}
    	Tp < class T > void write(T x) {
    			if(O > LIMIT) flush() ;
    			if(x < 0) {
    				quq[O ++] = 0x2d ;
    				x = -x ;
    			}
    			do {
    				ST[++ sz] = x % 0xa ^ 0x30 ;
    				x /= 0xa ;
    			} while(x) ;
    			while(sz) quq[O ++] = ST[sz --] ;
    			return ;
    	}
    	FILEOUT & operator << (int x) {
    		return write(x) , * this ;
    	}
    	FILEOUT & operator << (signed x) {
    		return write(x) , * this ;
    	}
    	FILEOUT & operator << (unsigned x) {
    		return write(x) , * this ;
    	}
    } out ;
    
    int k , p , n , m ;
    
    const int maxn = 5e4 + 45 ;
    int s[maxn] ;
    struct mat {
    	int a[2][2] ;
    	~ mat () {
    		clear() ;
    	}
    	void clear() {
    		memset(a , 0 , sizeof(a)) ;
    	}
    
    	int * operator [] (int x) {
    		return a[x] ;
    	}
    } ;
    
    mat b[maxn] ;
    mat operator * (mat a , mat b) {
    	mat c ;
    	for(int i = 0 ; i < 2 ; i ++)
    		for(int j = 0 ; j < 2 ; j ++)
    			c[i][j] = 0 ;
    	for(int i = 0 ; i < 2 ; i ++)
    		for(int j = 0 ; j < 2 ; j ++)
    			for(int k = 0 ; k < 2 ; k ++)
    				c[i][j] = (c[i][j] + a[i][k] * b[k][j] % p) % p ;
    	return c ;
    }
    
    mat operator *= (mat & a , mat b) {
    	return a = a * b ;
    }
    
    mat qpow(mat f , mat bs , int y) {
    	for( ; y ; y >>= 1 , bs *= bs)
    		if(y & 1) f *= bs ;
    	return f ;
    }
    
    mat a[maxn] ;
    mat sum[maxn << 2] ;
    mat ans ;
    
    void build(int l , int r , int rt) {
    	if(l == r) {
    		sum[rt][0][0] = 0 , sum[rt][0][1] = s[l - 1] ;
    		sum[rt][1][0] = 1 , sum[rt][1][1] = s[l % n] ;
    		b[l] = a[l] = sum[rt] ;
    		return ;
    	}
    	int mid = l + r >> 1 ;
    	build(l , mid , rt << 1) , build(mid + 1 , r , rt << 1 | 1) ;
    	sum[rt] = sum[rt << 1] * sum[rt << 1 | 1] ;
    }
    
    void change(int l , int r , int rt , int x , mat v) {
    	if(l == r) {
    		sum[rt] = v ;
    		return ;
    	}
    	int mid = l + r >> 1 ;
    	(x <= mid) ? change(l , mid , rt << 1 , x , v)
    	: change(mid + 1 , r , rt << 1 | 1 , x , v) ;
    	sum[rt] = sum[rt << 1] * sum[rt << 1 | 1] ;
    }
    
    struct que {
    	int x , y , k ;
    } q[maxn << 1] ;
    
    signed main() {
    #ifdef _WIN64
    	freopen("testdata.in" , "r" , stdin) ;
    #else
    	ios_base :: sync_with_stdio(false) ;
    	cin.tie(nullptr) , cout.tie(nullptr) ;
    #endif
    // code begin.
    	in >> k >> p >> n ;
    	for(int i = 0 ; i < n ; i ++) in >> s[i] ;
    	build(1 , n , 1) ;
    	in >> m ;
    	for(int i = 1 ; i <= m ; i ++)
    		in >> q[i].x >> q[i].y ;
    	for(int i = 1 ; i <= m ; i ++) {
    		q[i].y %= p ;
    		q[i].k = 1 ;
    		q[i + m] = q[i] ;
    		q[i + m].x ++ ;
    		q[i + m].k -- ;
    	}
    	m <<= 1 ;
    	sort(q + 1 , q + m + 1 ,
    	[](const que & x , const que & y) {
    		return x.x < y.x ;
    	}) ;
    	while(m > 0 && q[m].x > k) -- m ;
    	ans.clear() ;
    	ans[0][1] = 1 ;
    	int lasbl = 0 ;
    	for(int i = 1 , j = 1 ; i <= m ; i = ++ j) {
    		int bl = (q[i].x - 1) / n ;
    		while(j < m && bl == (q[j + 1].x - 1) / n) ++ j ;
    		ans = qpow(ans , sum[1] , bl - lasbl) ;
    		lasbl = bl ;
    		for(int qwq = i ; qwq <= j ; qwq ++) {
    			int d = (q[qwq].x - 1) % n + 1 ;
    			b[d][q[qwq].k][1] = q[qwq].y ;
    			change(1 , n , 1 , d , b[d]) ;
    		}
    		if(bl == k / n) break ;
    		ans = ans * sum[1] ;
    		lasbl = bl + 1 ;
    		for(int qwq = i ; qwq <= j ; qwq ++) {
    			int d = (q[qwq].x - 1) % n + 1 ;
    			b[d] = a[d] ;
    			change(1 , n , 1 , d , b[d]) ;
    		}
    	}
    	int bl = k / n ;
    	ans = qpow(ans , sum[1] , bl - lasbl) ;
    	for(int i = 1 ; i <= k % n ; i ++)
    		ans *= b[i] ;
    	out << ans[0][0] << '
    ' ;
    	return out.flush() , 0 ;
    // code end.
    }
    
  • 相关阅读:
    关于delphi xe8安装完之后的关键步骤
    delphi xe8开发安卓程序:访问服务器上的配置文件
    delphi grideh使用
    delphi 获取可执行文件的当前路径
    Delphi XE10下用FireDAC与SQLite连接要注意的问题
    Google Map Api 自定义maker样式和InfoWindow样式(叠加层)
    地理定位(navigator.geolocation)
    document.documentElement和document.body的区别
    【JavaScript】Function类型
    Ubuntu 14.04 安装 php5.6
  • 原文地址:https://www.cnblogs.com/Isaunoya/p/12250111.html
Copyright © 2020-2023  润新知