zoukankan      html  css  js  c++  java
  • 开始玩矩阵了!先来一道入门题![SDOI2008]递归数列

    [SDOI2008]递归数列

    题目描述

    一个由自然数组成的数列按下式定义:

    对于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的余数的值。

    输入输出格式

    输入格式:

    输入文件spp.in由四行组成。

    第一行是一个自然数k。

    第二行包含k个自然数b1, b2,...,bk。

    第三行包含k个自然数c1, c2,...,ck。

    第四行包含三个自然数m, n, p。

    输出格式:

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

    输入输出样例

    输入样例#1:
    2
    1 1
    1 1
    2 10 1000003
    
    输出样例#1:
    142

    说明

    对于100%的测试数据:

    1<= k <=15

    1 <= m <= n <= 1018

    对于20%的测试数据:

    1<= k <=15

    1 <= m <= n <= 106

    对于30%的测试数据:

    k=1 1 <= m <= n <= 1018

    对于所有测试数据:

    0<= b1, b2,... bk, c1, c2,..., ck<=109

    1 <= p <= 108

    挺水的一道题,推出了矩阵,然后前缀和搞搞也就简单了;

    矩阵如下:

    S[n]
    b[n]
    b[n-1]
    ...
    b[n-k+1]
    =
    1 c[1] ... c[k-1] c[k]
    0 c[1] ... c[k-1] c[k]
    0 1 ... 0 0
    0 0 ... 0 0
    0 0 ... 1 0
    *
     
    S[n-1]
    b[n-1]
    b[n-2]
    ...
    b[n-k+1]
    #include<bits/stdc++.h>
    #define ll long long
    #define maxn 20
    using namespace std;
    
    ll k,b[maxn],c[maxn],n,m,p,tot;
    
    struct mat{
        ll x,y;
        ll s[maxn][maxn];
    };
    
    mat operator *(mat a,mat b)
    {
        mat c;
        c.x = a.x;
        c.y = b.y;
        memset(c.s,0,sizeof(c.s));
        for(ll i=1;i<=a.x;i++)
            for(ll j=1;j<=b.y;j++)
                for(ll k=1;k<=b.x;k++)
                    c.s[i][j] = (c.s[i][j] + a.s[i][k] * b.s[k][j] % p) % p;
        return c;
    }
    
    mat ksm(mat a,ll ci)
    {
        mat ans;
        memset(ans.s,0,sizeof(ans.s));
        ans.x = ans.y = a.x;
        for(ll i=1;i<=ans.x;i++)
            ans.s[i][i] = 1;
        while(ci)
        {
            if(ci & 1) ans = ans * a;
            a = a * a;
            ci >>= 1;
        }
        return ans;
    }
    
    ll find(ll num)
    {
        if(num <= k)
        {    
            ll ans = 0;
            for(ll i=1;i<=num;i++) ans += b[i],ans %= p;
            return ans % p;
        }
        mat ans;
        memset(ans.s,0,sizeof(ans.s));
        ans.x = ans.y = k + 1;
        for(ll i=2;i<=k+1;i++)
            ans.s[1][i] = ans.s[2][i] = c[i - 1];
        ans.s[1][1] = 1;
        for(ll i=2;i<=k;i++)
            ans.s[i + 1][i] = 1;
        ans = ksm(ans , num - k);
        mat right;
        memset(right.s,0,sizeof(right.s));
        right.x = k + 1;
        right.y = 1;
        for(ll i=2;i<=k+1;i++)
            right.s[i][1] = b[k + 2 - i];
        right.s[1][1] = tot;
        right = ans * right;
        return right.s[1][1];
    }
    
    int main(){
        cin >> k;
        for(ll i=1;i<=k;i++) scanf("%d",&b[i]),tot += b[i];
        for(ll i=1;i<=k;i++) scanf("%d",&c[i]);
        cin >> m >> n >> p;
        cout << (find(n) - find(m - 1) + p) % p;
    }
  • 相关阅读:
    POJ 1436 Horizontally Visible Segments(线段树)
    POJ 1436 Horizontally Visible Segments(线段树)
    精益项目管理的可行性分析
    精益项目管理的可行性分析
    精益项目管理的可行性分析
    精益项目管理的可行性分析
    单点登录cas常见问题(二)
    单点登录cas常见问题(二)
    蓝氏兄弟依靠板栗东山再起,意外赚回八九万元
    元旦快乐,感谢一路相伴!
  • 原文地址:https://www.cnblogs.com/kczno1fans/p/7745078.html
Copyright © 2011-2022 走看看