bzoj3231: [Sdoi2008]递归数列

Posted WQHui

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3231: [Sdoi2008]递归数列相关的知识,希望对你有一定的参考价值。

3231: [Sdoi2008]递归数列

Time Limit: 1 Sec  Memory Limit: 256 MB

Description

一个由自然数组成的数列按下式定义:
对于i <= kai = 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
第四行包含三个自然数mnp

Output

仅包含一行:一个正整数,表示(am + am+1 + am+2 + ... + an) mod p的值。

Sample Input

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

 

以上是关于bzoj3231: [Sdoi2008]递归数列的主要内容,如果未能解决你的问题,请参考以下文章

bzoj3231[Sdoi2008]递归数列 矩阵乘法+快速幂

[SDOI2008]递归数列

开始玩矩阵了!先来一道入门题![SDOI2008]递归数列

[luogu2461 SDOI2008] 递归数列 (矩阵乘法)

bzoj 1000+AC

BZOJ3992: [SDOI2015]序列统计