bzoj3231: [Sdoi2008]递归数列
3231: [Sdoi2008]递归数列
Time Limit: 1 Sec Memory Limit: 256 MBDescription
一个由自然数组成的数列按下式定义:
对于i <= k:ai = bi
对于i > k: ai = c1ai-1 + c2ai-2 + ... + ckai-k
其中bj和 cj (1<=j<=k)是给定的自然数。写一个程序,给定自然数m <= n, 计算am + am+1 + am+2 + ... + an, 并输出它除以给定自然数p的余数的值。
Input
由四行组成。
第一行是一个自然数k。
第二行包含k个自然数b1, b2,...,bk。
第三行包含k个自然数c1, c2,...,ck。
第四行包含三个自然数m, n, p。
Output
仅包含一行:一个正整数,表示(am + am+1 + am+2 + ... + an) mod p的值。
Sample Input
2
1 1
1 1
2 10 1000003
1 1
1 1
2 10 1000003
Sample Output
142
HINT
对于100%的测试数据:
1<= k<=15
1 <= m <= n <= 1018
Source
很裸的矩阵快速幂模板题;
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 7 typedef long long ll; 8 ll ans1,ans2,p,n,m1,m2,res,v[28],c[28],a[28][28],ans[28][28],b[28][28]; 9 10 void cc(){ 11 for(ll i=1;i<=n+1;i++) 12 for(ll j=1;j<=n+1;j++){ 13 b[i][j]=0; 14 for(ll k=1;k<=n+1;k++) 15 b[i][j]=(b[i][j]+a[i][k]*ans[k][j]%p)%p; 16 } 17 for(ll i=1;i<=n+1;i++) 18 for(ll j=1;j<=n+1;j++) 19 ans[i][j]=b[i][j]; 20 } 21 22 void ch(){ 23 for(ll i=1;i<=n+1;i++) 24 for(ll j=1;j<=n+1;j++){ 25 b[i][j]=0; 26 for(ll k=1;k<=n+1;k++) 27 b[i][j]=(b[i][j]+a[i][k]*a[k][j]%p)%p; 28 } 29 for(ll i=1;i<=n+1;i++) 30 for(ll j=1;j<=n+1;j++) 31 a[i][j]=b[i][j]; 32 } 33 34 void init(){ 35 memset(a,0,sizeof(a)); 36 for(ll i=1;i<n;i++) a[i][i+1]=1; 37 for(ll i=1;i<=n;i++) 38 { 39 a[n][i]=c[i]; 40 a[n+1][i]=c[i]; 41 } 42 a[n+1][n+1]=1; 43 } 44 45 int main(){ 46 memset(v,0,sizeof(v)); ans1=ans2=0; 47 scanf("%lld",&n); 48 for(ll i=1;i<=n;i++) scanf("%lld",&v[i]); 49 for(ll i=1;i<=n;i++) scanf("%lld",&c[i]); 50 scanf("%lld%lld%lld",&m1,&m2,&p); 51 for(int i=1;i<=n;i++){ 52 v[i]=v[i]%p; 53 v[n+1]=(v[n+1]+v[i])%p; 54 c[i]=c[i]%p; 55 } 56 for(ll i=1;i<=n/2;i++) swap(c[i],c[n-i+1]); 57 for(ll i=1;i<=n+1;i++) ans[i][i]=1; 58 init(); 59 if(m1>m2){ 60 printf("0"); 61 return 0; 62 } 63 if(m1-1<=n){ 64 for(ll i=1;i<=m1-1;i++) 65 ans1=(ans1+v[i])%p; 66 if(m2<=n){ 67 for(ll i=1;i<=m2;i++) 68 ans2=(ans2+v[i])%p; 69 }else{ 70 m2=m2-n; 71 while(m2>0){ 72 if(m2%2==1) cc(); 73 m2=m2/2; 74 ch(); 75 } 76 for(ll i=1;i<=n+1;i++) 77 ans2=(ans2+v[i]*ans[n+1][i]%p)%p; 78 } 79 }else{ 80 m2=m2-m1+1; 81 m1=m1-1-n; 82 while(m1>0){ 83 if(m1%2==1) cc(); 84 m1=m1/2; 85 ch(); 86 } 87 for(ll i=1;i<=n+1;i++) 88 ans1=(ans1+v[i]*ans[n+1][i]%p)%p; 89 init(); 90 while(m2>0){ 91 if(m2%2==1) cc(); 92 m2=m2/2; 93 ch(); 94 } 95 for(ll i=1;i<=n+1;i++) 96 ans2=(ans2+v[i]*ans[n+1][i]%p)%p; 97 } 98 printf("%lld",((ans2-ans1)%p+p)%p); 99 }