cf575A Fibonotci
Fibonotci sequence is an integer recursive sequence defined by the recurrence relation
Fn = sn - 1·Fn - 1 + sn - 2·Fn - 2withF0 = 0, F1 = 1
Sequence s is an infinite and almost cyclic sequence with a cycle of length N. A sequence s is called almost cyclic with a cycle of length N if
, for i ≥ N, except for a finite number of values si, for which
(i ≥ N).
Following is an example of an almost cyclic sequence with a cycle of length 4:
s = (5,3,8,11,5,3,7,11,5,3,8,11,…)
Notice that the only value of s for which the equality
does not hold is s6 (s6 = 7 and s2 = 8). You are given s0, s1, ...sN - 1 and all the values of sequence s for which
(i ≥ N).
Find
.
The first line contains two numbers K and P. The second line contains a single number N. The third line contains N numbers separated by spaces, that represent the first N numbers of the sequence s. The fourth line contains a single number M, the number of values of sequence s for which
. Each of the following M lines contains two numbers j and v, indicating that
and sj = v. All j-s are distinct.
- 1 ≤ N, M ≤ 50000
- 0 ≤ K ≤ 1018
- 1 ≤ P ≤ 109
- 1 ≤ si ≤ 109, for all i = 0, 1, ...N - 1
- N ≤ j ≤ 1018
- 1 ≤ v ≤ 109
- All values are integers
Output should contain a single integer equal to
.
10 8
3
1 2 1
2
7 3
5 4
4
感觉是递推神题……f[n]=s[n-1]*f[n-1]+s[n-2]*f[n-2],而且{s[i]}是个T=5w的循环数列,而且还换掉了s[i]当中5w个点……
先不考虑几个s[i]的特殊点
都算到f[1e18]了肯定是要用到矩阵快速幂了
构建矩阵比较简单:
f[n] f[n-1] * s[n] 1 = f[n+1] f[n]
0 0 s[n-1] 0 0 0
那么
f[1] f[0] * s[1] 1 * s[2] 1 * ..... * s[n-1] 1 = f[n] f[n-1]
0 0 s[0] 0 s[1] 0 s[n-2] 0 0 0
然后注意到s[i]是个循环的
所以就是算出一个循环内的转移矩阵的乘积,一个循环是
s[1] 1 ~ s[T] 1
s[0] 0 s[T-1] 0
接下来直接快速幂即可。
然后考虑挖点的情况:对于一个s[k]的修改,实际上有两个矩阵受到了它的影响:
s[k] 1 和 s[k+1] 1
s[k-1] 0 s[k] 0
所以每个修改拆成2个对矩阵里头的值的修改。这样就是对矩阵的单点修改不超过10w个
所有s[k]的修改按照k排个序
然后维护一个线段树,保存一个周期内的矩阵的乘积(对你没看错,线段树存的是矩阵)
每次同一个周期内的修改就直接在线段树上单点修改,做完之后ans乘个当前1到T的区间积,然后再单点改回去,下个周期再改。这样每个修改就是logT的
改回去的时候搞个栈就好了
最后输出个答案矩阵的左上角
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<deque>
#include<set>
#include<map>
#include<ctime>
#define LL long long
#define inf 0x7ffffff
#define pa pair<int,int>
#define mkp(a,b) make_pair(a,b)
#define pi 3.1415926535897932384626433832795028841971
using namespace std;
inline LL read()
{
LL x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
LL k,mod,T,C,cnt;
LL s[];
struct matrix{
LL a[][];
inline void init(){a[][]=a[][]=a[][]=a[][]=;}
matrix operator *(matrix b)
{
matrix ans;ans.init();
for (int k=;k<=;k++)
for (int i=;i<=;i++)
for (int j=;j<=;j++)
ans.a[i][j]=(ans.a[i][j]+a[i][k]*b.a[k][j])%mod;
return ans;
}
}ans;
inline matrix getm(LL x)
{
matrix c;
c.a[][]=s[x];c.a[][]=;c.a[][]=s[x-];c.a[][]=;
return c;
}
struct segtree{
int l,r;
matrix m;
}t[];
int zhan[],top;
inline void update(int k){t[k].m=t[k<<].m*t[k<<|].m;}
inline void buildtree(int now,int l,int r)
{
t[now].l=l;t[now].r=r;
if (l==r)
{
t[now].m=getm(l);
return;
}
int mid=(l+r)>>;
buildtree(now<<,l,mid);
buildtree(now<<|,mid+,r);
update(now);
}
inline void change(int now,int x,matrix m)
{
int l=t[now].l,r=t[now].r;
if (l==r){t[now].m=m;return;}
int mid=(l+r)>>;
if (x<=mid)change(now<<,x,m);
else change(now<<|,x,m);
update(now);
}
inline matrix ask(int now,int x,int y)
{
int l=t[now].l,r=t[now].r;
if (l==x&&r==y)return t[now].m;
int mid=(l+r)>>;
if (y<=mid)return ask(now<<,x,y);
else if (x>mid)return ask(now<<|,x,y);
else return ask(now<<,x,mid)*ask(now<<|,mid+,y);
}
inline matrix quickpow(matrix a,LL b)
{
matrix s;s.init();s.a[][]=s.a[][]=;
while (b)
{
if (b&)s=s*a;
a=a*a;
b>>=;
}
return s;
}
struct cg{LL pos,rnk,x,op;}c[],lst;
bool operator <(cg a,cg b){return a.rnk<b.rnk||a.rnk==b.rnk&&a.pos<b.pos;}
bool operator <=(cg a,cg b){return !(b<a);}
int main()
{
k=read();mod=read();T=read();
if (k==){puts("");return ;}
if (k==){printf("%d\n",%mod);return ;}
k--;lst.rnk=k/T+(k%T!=);lst.pos=k%T;if (!lst.pos)lst.pos=T;
for (int i=;i<T;i++)s[i]=read();s[T]=s[];
C=read();
for (int i=;i<=C;i++)
{
LL a=read(),b=read();
c[++cnt].rnk=a/T+(a%T!=);
c[cnt].pos=a%T;if (!c[cnt].pos)c[cnt].pos=T;
c[cnt].x=b;c[cnt].op=; c[++cnt].rnk=a/T+;
c[cnt].pos=a%T+;
c[cnt].x=b;c[cnt].op=;
}
sort(c+,c+cnt+);
buildtree(,,T);
ans.a[][]=;
LL now2=;
for (int i=;i<=cnt;i++)
{
if(c[i]<=lst)
{
if (c[i].rnk-!=now2)
{
ans=ans*ask(,,T);
while (top){change(,zhan[top],getm(zhan[top]));top--;}
now2++;
if(now2!=c[i].rnk-)ans=ans*quickpow(ask(,,T),c[i].rnk--now2),now2=c[i].rnk-;
}
matrix chg=ask(,c[i].pos,c[i].pos);
if (c[i].op==)chg.a[][]=c[i].x;else chg.a[][]=c[i].x;
change(,c[i].pos,chg);
zhan[++top]=c[i].pos;
}else
{
if (now2<lst.rnk-)
{
ans=ans*ask(,,T);
while (top){change(,zhan[top],getm(zhan[top]));top--;}
now2++;
if (now2<lst.rnk-)ans=ans*quickpow(ask(,,T),lst.rnk--now2);
}
ans=ans*ask(,,lst.pos);
printf("%lld\n",ans.a[][]);return ;
}
}
if (now2<lst.rnk-)
{
ans=ans*ask(,,T);
while (top){change(,zhan[top],getm(zhan[top]));top--;}
now2++;
if (now2<lst.rnk-)ans=ans*quickpow(ask(,,T),lst.rnk--now2);
}
ans=ans*ask(,,lst.pos);
printf("%lld\n",ans.a[][]);return ;
}
cf 575A
cf575A Fibonotci的更多相关文章
- CF575A Fibonotci [线段树+矩阵快速幂]
题意 \(s\{\}\) 是一个循环数列 循环节为 \(n\),你可以改掉 \(m\) 项,这 \(m\) 项独立,且不影响循环节 考虑线段树维护矩阵,单点修改最多m次,每次矩阵快速幂就完事了 // ...
- Bubble Cup 8 finals A. Fibonotci (575A)
题意: 定义类循环序列为 长度无限,且除了有限个元素外,均满足s[i] ≡ s[i mod N] (i≥N). 现在有数列F,定义为 F[i] = s[i-2]*F[i-1] + s[i-1]*F[i ...
- codeforces575A Fibonotci
题目大意:f[k]=f[k-1]*s[(n-1)%n]+f[(k-2)]*s[(k-2)%n];会修改某一位置的s值,但循环不变,求f[k]; 矩阵快速幂裸题,由于有修改,所以需要线段树优化 #inc ...
- Codeforces 575A - Fibonotci
题面传送门 题意: 给出 \(s_0,s_1,s_2,\dots,s_{n-1}\),对于 \(i\geq n\),有 \(m\) 个 \(s_i\) 满足 \(s_i\neq s_{i\bmod n ...
- 「考试」联赛模拟36-39,noip晚间小测2-3
36.1 party(CF623D) 很是鸡贼的一道题 首先要明确一点,抓人是有策略,而不是随机的,可以认为等同于按一个给定的顺序猜人,那么这时猜中的概率就只是抓住这个人的概率了 对于每一次猜测,因为 ...
- IOI 2020 集训队作业胡扯
首先安慰自己:做的没集训队快很正常-- 很正常-- 做不完也很正常-- 很正常-- 全都不会做也很正常-- 很正常-- 表格 试题一 完成情况 试题二 完成情况 试题三 完成情况 cf549E cf6 ...
- IOI2020只因训队作业胡做
w a r n i n g ! 意 识 流 警 告 !!1 不想一个个发了,干脆直接发个合集得了qwq 感觉这辈子都做不完了\(Q\omega Q\) CF516D 写过题解了 CF505E 写过题解 ...
- IOI 2020 国家集训队作业
\(\checkmark\) 试题一 完成情况 试题二 完成情况 试题三 完成情况 cf549E cf674G arc103_f \(\checkmark\) cf594E agc034_f agc0 ...
随机推荐
- HTML iframe框架
iframe 作用: 就是在一个网页插入一个小窗口 窗口里面也是一个网页 <a href="http://www.baidu.com" target="da1& ...
- [文章泛读] The varying faces of a program transformation systems (ACM Inroads, 2012)
Beevi S. Nadera, D. Chitraprasad, and Vinod S. S. Chandra. 2012. The varying faces of a program tran ...
- 洛谷 P2947 [USACO09MAR]仰望Look Up
题目描述 Farmer John's N (1 <= N <= 100,000) cows, conveniently numbered 1..N, are once again stan ...
- App Transport Security has blocked a cleartext HTTP
打开info.plist源代码复制粘贴 <key>NSAppTransportSecurity</key> <dict> <!--Includ ...
- SQLite连接
SQLite -连接 SQLite的联接子句用于从数据库中的两个或多个表合并的记录.JOIN是用于通过使用共同的每个值从两个表结合域的装置. SQL定义了三个主要类型的连接: CROSS JOIN I ...
- codeforces Gym 100338C Important Roads (重建最短路图)
正反两次最短路用于判断边是不是最短路上的边,把最短路径上的边取出来建图.然后求割边.注意重边,和卡spfa. 正权,好好的dijkstra不用,用什么spfa? #include<bits/st ...
- python打开.pkl的文件并显示里面的内容
pkl文件是pyhthon里面保存文件的一种格式,如果直接打开会显示一堆序列化的东西.正确的打开方式如下: import cPickle as pickle f = open('path') info ...
- CPP-基础:运算符重载详解
1.运算符重载定义: C++中预定义的运算符的操作对象只能是基本数据类型.但实际上,对于许多用户自定义类型(例如类),也需要类似的运算操作.这时就必须在C++中重新定义这些运算符,赋予已有运算符新的功 ...
- SNP|RELP|genetic polymorphism|
5.3个体基因组呈现广泛变化 遗传多态性:一个基因座上存在多个等位基因(因为野生型不止一种基因)的现象,但是只有这多种等位基因满足:1.多个基因稳定存在2.基因在种群中数目大于1%时,认为该基因座多态 ...
- CAS (Compare and Swap)
synchronized是悲观锁 注意:实现了CAS的有原子类(AtomicInteger,AtomicLong,等等原子类) CAS 是乐观锁,一种高效实现线程安全性的方法 1.支持原子更新操作,适 ...