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 }
View Code

 

posted @ 2017-11-05 08:41  鲸头鹳  阅读(134)  评论(0编辑  收藏  举报