题目大意:f[k]=f[k-1]*s[(n-1)%n]+f[(k-2)]*s[(k-2)%n];会修改某一位置的s值,但循环不变,求f[k];
矩阵快速幂裸题,由于有修改,所以需要线段树优化
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define maxn 50005 5 #define f(c,d) ((1<<(c))*(d)) 6 struct node{ 7 ll x[2][2]; 8 }mt,mi,t,tt,x[17][maxn]; 9 int n,m,p; 10 ll k,s[maxn],ti; 11 pair<ll,ll>v[maxn]; 12 node operator * (node a,node b){ 13 node c=mt; 14 for(int i=0;i<2;++i) 15 for(int j=0;j<2;++j) 16 for(int k=0;k<2;++k) 17 c.x[i][j]=(c.x[i][j]+a.x[i][k]*b.x[k][j]%p)%p; 18 return c; 19 } 20 node operator ^ (node a,ll y){ 21 if(y==0)return mi; 22 node c=a;y--; 23 while(y){ 24 if(y&1)c=c*a; 25 y>>=1;a=a*a; 26 }return c; 27 } 28 node ask(int a,int b,int c,int d){ 29 if(f(c,d)==a&&f(c,d+1)==b)return x[c][d]; 30 c--;d=d<<1|1; 31 if(b<=f(c,d))return ask(a,b,c,d-1); 32 if(a>=f(c,d))return ask(a,b,c,d); 33 return ask(a,f(c,d),c,d-1)*ask(f(c,d),b,c,d); 34 } 35 node ask(int a,int b){ 36 if(a==b)return mi; 37 return ask(a,b,16,0); 38 } 39 void to(ll a){ 40 if(a/n-ti/n){ 41 t=t*ask(ti%n,n); 42 t=t*(x[16][0]^(a/n-ti/n-1)); 43 t=t*ask(0,a%n); 44 }else t=t*ask(ti%n,a%n); 45 ti=a; 46 } 47 int main(){ 48 scanf("%I64d%d",&k,&p); 49 mi.x[0][0]=mi.x[1][1]=1%p; 50 scanf("%d",&n); 51 for(int i=0;i<n;++i)scanf("%I64d",&s[i]); 52 for(int i=0;i<n;++i){ 53 x[0][i].x[0][1]=s[i]%p; 54 x[0][i].x[1][0]=1; 55 x[0][i].x[1][1]=s[(i+1)%n]%p; 56 } 57 for(int i=1;i<17;++i) 58 for(int j=0;f(i,j)<n;++j){ 59 x[i][j]=x[i-1][j<<1]; 60 if(f(i-1,(j<<1|1))<n)x[i][j]=x[i-1][j<<1]*x[i-1][j<<1|1]; 61 } 62 scanf("%d",&m); 63 for(int i=0;i<m;++i)scanf("%I64d%I64d",&v[i].first,&v[i].second); 64 sort(v,v+m); 65 ti=0; 66 t=mi; 67 for(int i=0;i<m;++i){ 68 if(v[i].first>k)break; 69 if(ti!=v[i].first){ 70 to(v[i].first-1); 71 tt.x[0][1]=s[ti%n]%p; 72 tt.x[1][0]=1; 73 tt.x[1][1]=v[i].second%p; 74 t=t*tt; 75 ti++; 76 } 77 if(ti==k)break; 78 ti++; 79 tt.x[0][1]=v[i].second%p; 80 tt.x[1][0]=1; 81 tt.x[1][1]=(v[i+1].first==ti?v[i+1].second:s[ti%n])%p; 82 t=t*tt; 83 } 84 to(k); 85 printf("%I64d ",t.x[1][0]); 86 return 0; 87 }