zoukankan      html  css  js  c++  java
  • [BZOJ3231][SDOI2008]递归数列

    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
    第四行包含三个自然数m, n, p

    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 <= 10^18


    矩乘没跑了...

    信心满满的交上去wa,cao没开long long;

    又信心满满地交上去爆负数出来,woc?这为什么会有负数。

    不管了+mod再%mod交上去,wocA了?

    为什么会出负数...

    其实就是前缀和,跑两次,一次是n-k,一次是m-k-1,然后把sum做差。

    矩阵...不想写了...算了写写吧.

     0  1  0  0      a1       a2  

     0  0  1  0        a2        a3

     0  0  0  1           *   a3     =         a4

    c4 c3 c2 c1       a4         a5

    c4 c3 c2 1        sum                   sum'

    这是k=4的情况...

    还有要注意的是n或者m小于k,要特判。


    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    using namespace std;
    #define int long long
    inline int read(){
        #define gc getchar()
        int res=0;char ch=gc;
        while(!isdigit(ch))ch=gc;
        while(isdigit(ch)){res=(res<<3)+(res<<1)+(ch^48);ch=gc;}
        return res;
    }
    int k, m, n, p;
    int b[16], c[16];
    
    struct Mat
    {
        int a[19][19];
        Mat() {memset(a, 0, sizeof a);}
        inline void init(){for(int i=1;i<=18;i++)a[i][i] = 1;}
        friend Mat operator *(Mat x, Mat y)
        {
            Mat z;
            for (int k = 1 ; k <= 18 ; k ++)
                for (int i = 1 ; i <= 18 ; i ++)
                    for (int j = 1 ; j <= 18 ; j ++)
                        z.a[i][j] = (z.a[i][j] + x.a[i][k] * y.a[k][j]) % p;
            return z;
        }
        friend Mat operator ^ (Mat x, int y)
        {
            Mat res;res.init();
            while(y)
            {
                if (y&1) res = res * x;
                x = x * x;
                y >>= 1;
            }
            return res;
        }
    }l, r, A, B;
    int qzh[20];
    signed main()
    {
        k = read();
        for (int i = 1 ; i <= k ; i ++) b[i] = read(), qzh[i] = qzh[i-1] + b[i];
        for (int i = 1 ; i <= k ; i ++) c[i] = read();
        m = read(), n = read(), p = read();
        for (int i = 1 ; i <= k ; i ++) b[i] %= p, c[i] %= p;
        
        for (int i = 1 ; i < k ; i ++) A.a[i][i+1] = 1;
        for (int i = 1 ; i <= k ; i ++) A.a[k][i] = c[k-i+1];
        for (int i = 1 ; i <= k ; i ++) A.a[k+1][i] = c[k-i+1]; 
        A.a[k+1][k+1] = 1;
        for (int i = 1 ; i <= k ; i ++) B.a[i][1] = b[i];
        B.a[k+1][1] = qzh[k] % p;
        
        if (m >= k + 1)l = (A ^(m - k - 1)) * B;
        r = (A ^ (n - k)) * B;
        
        if (m <= k) 
        {
            for (int i = 1 ; i <= k ; i ++) qzh[i] %= p;
            if (n <= k) printf("%lld
    ", qzh[n] - qzh[m-1]);
            else printf("%lld
    ", r.a[k+1][1] - qzh[m-1]);
            return 0;
        }
        
        printf("%lld
    ", (r.a[k+1][1] - l.a[k+1][1] + p) % p);
        return 0;
    }

     $sum_{age=16}^{18} hardworking = success$

  • 相关阅读:
    STM32位带操作
    url参数 加密
    object.key 对象的键排序 可能出现的问题
    在vue项目中 获取容器的高度
    navigator 判断移动端是Android还是iOS
    Nginx下载地址
    Sublime Text3快捷键大全
    鼠标拖着元素飞
    g6 cavans
    vue img标签图片加载时 闪烁
  • 原文地址:https://www.cnblogs.com/BriMon/p/9384714.html
Copyright © 2011-2022 走看看