BZOJ 3231: [Sdoi2008]递归数列( 矩阵快速幂 )

矩阵乘法裸题..差分一下然后用矩阵乘法+快速幂就可以了. 

---------------------------------------------------------------------------------

#include<cstdio>
#include<cstring>
#include<algorithm>
 
using namespace std;
 
const int maxn = 20;
 
typedef long long ll;
typedef int mat[maxn][maxn];
 
ll n, m;
int p, k, ans, sm;
int b[maxn], c[maxn];
mat Q, res, tmp;
 
inline void upd(int &x, int t) {
if((x += t) >= p) x -= p;
if(x < 0) x += p;
}
 
void Init() {
ans = sm = 0;
scanf("%d", &k);
for(int i = 0; i < k; i++)
scanf("%d", b + i);
for(int i = 0; i < k; i++)
scanf("%d", c + i);
scanf("%lld%lld%d", &m, &n, &p);
for(int i = 0; i < k; i++)
upd(sm, b[i]);
}
 
void makeMatrix() {
Q[0][0] = 1;
Q[1][0] = 0;
for(int i = 1; i <= k; i++)
Q[0][i] = Q[1][i] = c[i - 1];
for(int i = 2; i <= k; i++)
for(int j = 0; j <= k; j++)
Q[i][j] = (j + 1 == i);
for(int i = 0; i <= k; i++)
for(int j = 0; j <= k; j++)
res[i][j] = (i == j);
}

  

void Mult(mat &a, mat b) {
for(int i = 0; i <= k; i++)
for(int j = 0; j <= k; j++)
tmp[i][j] = 0;
for(int i = 0; i <= k; i++)
for(int v = 0; v <= k; v++)
for(int j = 0; j <= k; j++)
upd(tmp[i][j], ll(a[i][v]) * b[v][j] % p);
for(int i = 0; i <= k; i++)
for(int j = 0; j <= k; j++)
a[i][j] = tmp[i][j];
}
 
int calc(ll x) {
makeMatrix();
x -= k;
for(; x; x >>= 1, Mult(Q, Q))
if(x & 1) Mult(res, Q);
int ret = 0;
upd(ret, ll(res[0][0]) * sm % p);
for(int i = 1; i <= k; i++)
upd(ret, ll(res[0][i]) * b[k - i] % p);
return ret;
}
 
void Work() {
if(--m <= k) {
for(int i = 0; i < m; i++)
upd(ans, -c[i]);
} else
upd(ans, -calc(m));
upd(ans, calc(n));
printf("%d\n", ans);
}
 
int main() {
Init();
Work();
return 0;
}

--------------------------------------------------------------------------------- 

3231: [Sdoi2008]递归数列

Time Limit: 1 Sec  Memory Limit: 256 MB
Submit: 526  Solved: 229
[Submit][Status][Discuss]

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

 

posted @ 2016-01-06 14:01  JSZX11556  阅读(317)  评论(0编辑  收藏  举报