zoukankan      html  css  js  c++  java
  • 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 ", 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

  • 相关阅读:
    重温Delphi之:面向对象
    Delphi2007卸载后无法再安装
    ERP开源框架 + 二次开发平台 介绍
    CodeGear RAD 2007 SP4 最新下载及破解
    Delphi XE中类成员的访问权限(新增了strict private和strict protected,还有automated)
    Delphi学习技巧
    Codeforce 101B. Buses(线段树or树状数组+离散化)
    Codeforce 101B. Buses(线段树or树状数组+离散化)
    codeforce -39E-What Has Dirichlet Got to Do with That?(博弈+dfs)
    codeforce -39E-What Has Dirichlet Got to Do with That?(博弈+dfs)
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/5105358.html
Copyright © 2011-2022 走看看