日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

nssl1453-Fibonacci数列【矩阵乘法,线段树】

發布時間:2023/12/3 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 nssl1453-Fibonacci数列【矩阵乘法,线段树】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

正題


題目大意

給出nnnsi(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的快的轉移相同,我們可以用矩陣乘法快速冪計算。

那么我們可以在有修改的間隔之中可以用矩陣乘法快速冪算,然后對于中間修改的點,我們可以用線段樹維護區間的矩陣乘法積進行單點修改即可。


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; }

總結

以上是生活随笔為你收集整理的nssl1453-Fibonacci数列【矩阵乘法,线段树】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。