luogu2461递归数列

来源:互联网 发布:淘宝店铺歌曲 编辑:程序博客网 时间:2024/05/21 07:10

题目描述

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

对于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

这里写图片描述

这里写代码片#include<cstdio>#include<cstring>#include<iostream>#define LL long long using namespace std;const int N=20;int k;LL n,mm,mod;LL b[N],c[N];LL tot=0;struct node{    LL m[N][N];    node operator *(const node &a) const{        node ans;        for (int i=1;i<=k;i++)            for (int j=1;j<=k;j++)            {                ans.m[i][j]=0;                for (int l=1;l<=k;l++)                    ans.m[i][j]=(ans.m[i][j]+m[i][l]*a.m[l][j])%mod;            }        return ans;  ///    }    void clear()    {        memset(m,0,sizeof(m));    }    LL KSM(LL pp)    {        LL p;        if (pp<=k)  //用不到矩乘         {            LL an=0;            for (int i=1;i<=pp;i++)  //直接暴力                 an=(an+b[i])%mod;            return an%mod;        }        p=pp-k; //真心。。对样例调一调就好了         node ans=(*this),a=(*this);        while (p)        {            if (p&1)               ans=ans*a;            a=a*a;            p>>=1;        }        LL r=0;        for (int i=1;i<k;i++)            r=(r+(ans.m[i][k]*b[k-i])%mod)%mod;  //计算前缀和         r=(r+(tot*ans.m[k][k])%mod)%mod;        return r;  //sum    }};int main(){    scanf("%d",&k);    for (int i=1;i<=k;i++) scanf("%lld",&b[i]);     for (int i=1;i<=k;i++) scanf("%lld",&c[i]);    scanf("%lld%lld%lld",&mm,&n,&mod);    for (int i=1;i<=k;i++) tot=(tot+b[i]%mod)%mod;  //tot前缀和     node m,t;    m.clear(); t.clear();    for (int i=1;i<=k;i++)   //矩阵的初始值     { //在矩阵中我们要维护一个前缀和         m.m[i][1]=c[i];        m.m[i][k+1]=c[i];        t.m[i][1]=c[i];        t.m[i][k+1]=c[i];    }    for (int i=1;i<k;i++) m.m[i][i+1]=1,t.m[i][i+1]=1;    m.m[k+1][k+1]=1;    t.m[k+1][k+1]=1;    k++;    LL an=0;    an+=m.KSM(n);    an-=t.KSM(mm-1);    printf("%lld",(an+mod)%mod);  //题目有漏洞,在最后的%处理时要先+mod再%     return 0;}
原创粉丝点击