题意

\(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] << '\n' ;
return out.flush() , 0 ;
// code end.
}

CF575A Fibonotci [线段树+矩阵快速幂]的更多相关文章

  1. Wannafly Winter Camp 2019.Day 8 div1 E.Souls-like Game(线段树 矩阵快速幂)

    题目链接 \(998244353\)写成\(99824435\)然后调这个线段树模板1.5h= = 以后要注意常量啊啊啊 \(Description\) 每个位置有一个\(3\times3\)的矩阵, ...

  2. 线段树+矩阵快速幂 Codeforces Round #373 (Div. 2) E

    http://codeforces.com/contest/719/problem/E 题目大意:给你一串数组a,a[i]表示第i个斐波那契数列,有如下操作 ①对[l,r]区间+一个val ②求出[l ...

  3. CF719E(线段树+矩阵快速幂)

    题意:给你一个数列a,a[i]表示斐波那契数列的下标为a[i],求区间对应斐波那契数列数字的和,还要求能够维护对区间内所有下标加d的操作 分析:线段树 线段树的每个节点表示(f[i],f[i-1])这 ...

  4. Codeforces 719E [斐波那契区间操作][矩阵快速幂][线段树区间更新]

    /* 题意:给定一个长度为n的序列a. 两种操作: 1.给定区间l r 加上某个数x. 2.查询区间l r sigma(fib(ai)) fib代表斐波那契数列. 思路: 1.矩阵操作,由矩阵快速幂求 ...

  5. 【66测试20161115】【树】【DP_LIS】【SPFA】【同余最短路】【递推】【矩阵快速幂】

    还有3天,今天考试又崩了.状态还没有调整过来... 第一题:小L的二叉树 勤奋又善于思考的小L接触了信息学竞赛,开始的学习十分顺利.但是,小L对数据结构的掌握实在十分渣渣.所以,小L当时卡在了二叉树. ...

  6. 【XSY2524】唯一神 状压DP 矩阵快速幂 FFT

    题目大意 给你一个网格,每个格子有概率是\(1\)或是\(0\).告诉你每个点是\(0\)的概率,求\(1\)的连通块个数\(\bmod d=0\)的概率. 最开始所有格子的概率相等.有\(q\)次修 ...

  7. 培训补坑(day10:双指针扫描+矩阵快速幂)

    这是一个神奇的课题,其实我觉得用一个词来形容这个算法挺合适的:暴力. 是啊,就是循环+暴力.没什么难的... 先来看一道裸题. 那么对于这道题,显然我们的暴力算法就是枚举区间的左右端点,然后通过前缀和 ...

  8. 【对不同形式矩阵的总结】WC 2009 最短路径问题(线段树+矩阵乘法)

    题意 ​ 题目链接:https://www.luogu.org/problem/P4150 ​ 一个 \(6\times n\) 的网格图,每个格点有一个初始权值.有两种操作: 修改一个格子的权值 求 ...

  9. 【模板】矩阵快速幂 洛谷P2233 [HNOI2002]公交车路线

    P2233 [HNOI2002]公交车路线 题目背景 在长沙城新建的环城公路上一共有8个公交站,分别为A.B.C.D.E.F.G.H.公共汽车只能够在相邻的两个公交站之间运行,因此你从某一个公交站到另 ...

随机推荐

  1. DBA常用SQL之DDL生成语句-2

    ------数据迁移常用SQL SELECT 'DROP USER '||u.username ||' CASCADE;' AS dropstrs FROM DBA_USERS U where u.u ...

  2. 第3章 JDK并发包(四)

    3.2.5 自定义线程创建:ThreadFactory 线程池的主要作用是为了线程复用,也就是避免了线程的频繁创建. ThreadFactory是一个接口,它只有一个方法,用来创建线程: Thread ...

  3. vs 搭配 Linux 开发

    这是一篇翻译,为什么突然想翻译文章了呢,因为很多大佬们都说英语对程序员还是挺重要的,毕竟互联网的最新技术基本都在歪果仁那边,如果英语不好,不会看国外的文档的话,将会错失接触第一手资料的机会,失去很多先 ...

  4. Java开发最佳实践(一) ——《Java开发手册》之"编程规约"

    Java开发手册版本更新说明 专有名词解释 一. 编程规约 (一) 命名风格 (二) 常量定义 (三) 代码格式 (四) OOP 规约 (五) 集合处理 (六) 并发处理 (七) 控制语句 (八) 注 ...

  5. 我的一个React路由嵌套(多级路由),路由传参之旅

    在上一篇react路由之旅中,我们简单地配置了react,进行了react路由及相关知识的学习,引入以及实现一个局部跳转的功能,接下来就是深入学习路由的嵌套以及传参,这是工作中主要用要的. 我的rea ...

  6. 数据算法 --hadoop/spark数据处理技巧 --(1.二次排序问题 2. TopN问题)

    一.二次排序问题. MR/hadoop两种方案: 1.让reducer读取和缓存给个定键的所有值(例如,缓存到一个数组数据结构中,)然后对这些值完成一个reducer中排序.这种方法不具有可伸缩性,因 ...

  7. hive执行计划简单分析

    原始SQL: select a2.ISSUE_CODE as ISSUE_CODE, a2.FZQDM as FZQDM, a2.FZQLB as FZQLB, a2.FJJDM as FJJDM, ...

  8. Waymo-自动驾驶长尾问题挑战(2019)

    尽管Waymo已经在开放道路上积累超过10 Million Miles,Waymo的工程师们仍然发现有层出不穷的新自动驾驶场景待解决. 1.自动驾驶长尾场景举例 场景一:一个骑自行车的人手中拿着一个S ...

  9. springmvc maven idea 多模块开发(四):建立Web子模块

    先建立web的父模块,其他子web模块建立在该父模块之下,该模块打包方式选择为pom 建立实际web模块,右键点击web-parent,建立方法同上,打包方式为war 建立好后的目录结构如下: 手工建 ...

  10. 【转载】python_logging模块

    原文:https://www.cnblogs.com/liujiacai/p/7804848.html 1 logging模块简介 logging模块是Python内置的标准模块,主要用于输出运行日志 ...