【SDOI 2008】 递归数列

【题目链接】

          点击打开链接

【算法】

          矩阵乘法优化递推

          由于本博客不支持数学公式,所以不能将矩阵画出来,请谅解!

【代码】

         

#include<bits/stdc++.h>
using namespace std;
#define MAXK 18

struct Matrix 
{
        long long mat[MAXK][MAXK];
};

int i,k;
long long n,m,p,sum;
long long b[MAXK],c[MAXK];

template <typename T> inline void read(T &x)
{
    long long f = 1; x = 0;
    char c = getchar();
    for (; !isdigit(c); c = getchar()) { if (c == '-') f = -f; }
    for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
    x *= f;
}
template <typename T> inline void write(T x)
{
    if (x < 0)
    {
        putchar('-');
        x = -x;
    }
    if (x > 9) write(x/10);
    putchar(x%10+'0');
}
template <typename T> inline void writeln(T x)
{
    write(x);
    puts("");
}

inline void multipy(Matrix &a,Matrix b)
{
        int i,j,t;
        Matrix ans;
        memset(ans.mat,0,sizeof(ans.mat));
        for (i = 1; i <= k + 1; i++)
        {
                for (j = 1; j <= k + 1; j++)
                {
                        for (t = 1; t <= k + 1; t++)
                        {
                                ans.mat[i][j] = (ans.mat[i][j] + a.mat[i][t] * b.mat[t][j]) % p;
                        }
                }
        }
        a = ans;
}
inline long long solve(long long n)
{
        Matrix a,res;
        int i,j;
        long long ans = 0;
        memset(a.mat,0,sizeof(a.mat));
        for (i = 2; i <= k + 1; i++) a.mat[1][i] = a.mat[2][i] = c[i-1];
        for (i = 3; i <= k + 1; i++) a.mat[i][i-1] = 1;
        a.mat[1][1] = 1;
        memset(res.mat,0,sizeof(res.mat));
        for (i = 1; i <= k + 1; i++) res.mat[i][i] = 1;
        while (n > 0)
        {
                if (n & 1) multipy(res,a);
                multipy(a,a);
                n >>= 1;
        }
        ans = sum;
        for (i = 2; i <= k + 1; i++) ans = (ans + res.mat[1][i] * b[k-i+2]) % p;
        return ans;
}
inline long long query(long long n)
{
        int i;
        long long ans = 0;
        if (n <= k)
        {
                for (i = 1; i <= n; i++) ans = (ans + b[i]) % p;
                return ans;
        } else return solve(n-k);
}

int main() {
        
        read(k);
        for (i = 1; i <= k; i++) read(b[i]);
        for (i = 1; i <= k; i++) read(c[i]);
        read(m); read(n); read(p);
        for (i = 1; i <= k; i++) sum = (sum + b[i]) % p;
        writeln((query(n) - query(m-1) + p) % p);
        
        return 0;
    
}

 

posted @ 2018-05-26 10:43  evenbao  阅读(241)  评论(0编辑  收藏  举报