nssl1453-Fibonacci数列【矩阵乘法,线段树】
生活随笔
收集整理的這篇文章主要介紹了
nssl1453-Fibonacci数列【矩阵乘法,线段树】
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
正題
題目大意
給出nnn和si(i∈[0..n?1])s_i(i\in[0..n-1])si?(i∈[0..n?1]),對于大部分情況有sx=sx%ns_x=s_{x\%n}sx?=sx%n?。
有遞推式Fi=Fi?1si?1+Fi?2si?2F_i=F_{i-1}s_{i-1}+F_{i-2}s_{i-2}Fi?=Fi?1?si?1?+Fi?2?si?2?
有mmm個情況的sx!=sx%ns_x!=s_{x\% n}sx?!=sx%n?給出這些情況的sxs_xsx?的值
求FKF_KFK?
解題思路
考慮沒有mmm的情況,每個長度為nnn的快的轉(zhuǎn)移相同,我們可以用矩陣乘法快速冪計算。
那么我們可以在有修改的間隔之中可以用矩陣乘法快速冪算,然后對于中間修改的點,我們可以用線段樹維護區(qū)間的矩陣乘法積進行單點修改即可。
codecodecode
#include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const ll N=5e5+10; struct matrix{ll a[2][2]; }w[N*4],ans,f,pre[N],r[N]; struct node{ll x,y,f; }q[N]; ll n,m,K,P,s[N]; matrix operator*(matrix a,matrix b){matrix c;memset(c.a,0,sizeof(c.a));for(ll i=0;i<2;i++)for(ll j=0;j<2;j++)for(ll k=0;k<2;k++)(c.a[i][j]+=b.a[i][k]*a.a[k][j]%P)%=P;return c; } void Build(ll x,ll L,ll R){if(L==R){w[x].a[0][1]=1;w[x].a[1][0]=s[L-1];w[x].a[1][1]=s[L];pre[L]=r[L]=w[x];return;}ll mid=(L+R)>>1;Build(x*2,L,mid);Build(x*2+1,mid+1,R);w[x]=w[x*2]*w[x*2+1];return; } void Change(ll x,ll L,ll R,ll pos,matrix val){if(L==R){w[x]=val;return;}ll mid=(L+R)>>1;if(pos<=mid)Change(x*2,L,mid,pos,val);if(pos>mid)Change(x*2+1,mid+1,R,pos,val);w[x]=w[x*2]*w[x*2+1];return; } matrix Ask(ll x,ll L,ll R,ll l,ll r){if(L==l&&R==r)return w[x];ll mid=(L+R)>>1;if(r<=mid)return Ask(x*2,L,mid,l,r);if(l>mid)return Ask(x*2+1,mid+1,R,l,r);return Ask(x*2,L,mid,l,mid)*Ask(x*2+1,mid+1,R,mid+1,r); } bool cmp(node x,node y) {return x.x<y.x;} matrix power(ll b){matrix ans,x=f;ans.a[0][0]=1;ans.a[0][1]=0;ans.a[1][0]=0;ans.a[1][1]=1;while(b){if(b&1)ans=ans*x;x=x*x;b>>=1;} return ans; } int main() {scanf("%lld%lld",&K,&P);scanf("%lld",&n);for(ll i=0;i<n;i++)scanf("%lld",&s[i]);s[n]=s[0]; Build(1,1,n);f=w[1];ll M;scanf("%lld",&M);for(ll i=1;i<=M;i++){ll x,y;scanf("%lld%lld",&x,&y);q[++m].x=x;q[m].y=y;q[m].f=1;q[++m].x=x+1;q[m].y=y;q[m].f=0;}sort(q+1,q+1+m,cmp);ans.a[0][0]=ans.a[1][1]=1;ll zz=0;for(ll i=1,j;i<=m;i=j+1){j=i;ll c=(q[i].x-1)/n;while(j<m&&(q[j+1].x-1)/n<=c)j++;for(ll k=i;k<=j;k++){ll pos=(q[k].x-1)%n+1;r[pos].a[1][q[k].f]=q[k].y;Change(1,1,n,pos,r[pos]);}if(c==K/n)break;ans=ans*power(c-zz);ans=ans*w[1];zz=c+1;for(ll k=i;k<=j;k++){ll pos=(q[k].x-1)%n+1; r[pos]=pre[pos];Change(1,1,n,pos,r[pos]);}}ans=ans*power(K/n-zz);for(ll i=1;i<=K%n;i++)ans=ans*r[i];printf("%lld",ans.a[0][1]);return 0; }總結(jié)
以上是生活随笔為你收集整理的nssl1453-Fibonacci数列【矩阵乘法,线段树】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 视频转音频的简单方法视频转音频怎么操作
- 下一篇: 电脑上也能玩阴阳师如何在电脑上玩阴阳师