BZOJ 3231: [Sdoi2008]递归数列 (JZYZOJ 1353) 矩阵快速幂
和斐波那契一个道理在最后加一个求和即可
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 //using namespace std; 5 const int maxn=10010; 6 const double eps=1e-8; 7 long long modn; 8 long long n,l,r; 9 long long b[20]={}; 10 struct mat{ 11 long long e[20][20]; 12 mat(){ memset(e,0,sizeof(e)); } 13 }; 14 mat a; 15 mat Mul(mat x,mat y){ 16 mat z; 17 for(int i=1;i<=n+1;i++){ 18 for(int j=1;j<=n+1;j++){ 19 for(int k=1;k<=n+1;k++){ 20 z.e[i][j]+=x.e[i][k]*y.e[k][j]; 21 z.e[i][j]%=modn; 22 } 23 } 24 } 25 return z; 26 } 27 mat Pow(mat x,long long k){ 28 mat z; 29 for(int i=1;i<=n+1;i++){ 30 z.e[i][i]=1; 31 } 32 while(k>0){ 33 if(k&1){ 34 z=Mul(z,x); 35 } 36 x=Mul(x,x); 37 k/=2; 38 }/*for(int i=1;i<=n;i++){ 39 for(int j=1;j<=n;j++){ 40 std::cout<<z.e[i][j]<<' '; 41 } 42 std::cout<<std::endl; 43 }*/ 44 return z; 45 } 46 long long doit(long long x){ 47 if(x<n){ 48 return b[x+1]; 49 } 50 mat z=Pow(a,x-n+1); 51 long long ans=0,s=0,d=0; 52 for(int i=1;i<=n+1;i++){ 53 d+=z.e[n][i]*b[i]; 54 s+=z.e[n+1][i]*b[i]; 55 d%=modn;s%=modn; 56 } 57 ans=(s+d)%modn; 58 ans%=modn; 59 return ans; 60 } 61 int main(){ 62 scanf("%lld",&n); 63 n+=1; 64 for(int i=2;i<=n;i++){ 65 scanf("%lld",&b[i]); 66 b[n+1]+=b[i]; 67 } 68 b[n+1]-=b[n]; 69 for(int i=n;i>1;i--){ 70 scanf("%lld",&a.e[n][i]); 71 } 72 long long l,r; 73 scanf("%lld%lld%lld",&l,&r,&modn); 74 for(int i=2;i<=n;i++){ 75 b[i]%=modn; 76 a.e[i-1][i]=1;a.e[n][i]%=modn; 77 } 78 a.e[n+1][n+1]=1,a.e[n+1][n]=1; 79 /*for(int i=1;i<=n+1;i++){ 80 for(int j=1;j<=n+1;j++){ 81 std::cout<<a.e[i][j]<<' '; 82 } 83 std::cout<<std::endl; 84 }*/ 85 long long ans=(doit(r)-doit(l-1)+modn)%modn; 86 printf("%lld\n",ans); 87 return 0; 88 }