BZOJ:3231: [Sdoi2008]递归数列
题解:
矩阵乘法,在矩阵中构造当前前缀和;
注意:for(int/long long ;;);
#include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long Lint; Lint n,m; int k,p; int b[200]; int c[200]; Lint tmp1,tmp2; Lint sum; int minit(){ tmp1=tmp2=sum=0; } struct Matrix{ Lint e[200][200]; Matrix(){ memset(e,0,sizeof(e)); } int clear(){ memset(e,0,sizeof(e)); } }t,x,y,z,ret; int Mul(){ z.clear(); for(int i=0;i<=k;++i){ for(int j=0;j<=k;++j){ for(int r=0;r<=k;++r){ z.e[i][j]=(z.e[i][j]+x.e[i][r]*y.e[r][j])%p; } } } } int Ksm(Lint p){ ret.clear(); for(int i=0;i<=k;++i)ret.e[i][i]=1; while(p){ if(p<0)return 0; if(p&1){ x=ret;y=t;Mul(); ret=z; } p>>=1; x=t;y=t;Mul(); t=z; } } int main(){ minit(); scanf("%d",&k); for(int i=1;i<=k;++i)scanf("%d",&b[i]); for(int i=1;i<=k;++i)scanf("%d",&c[i]); scanf("%lld%lld%d",&n,&m,&p); for(int i=1;i<=k;++i)sum=(sum+b[i])%p; if(m<=k){ for(int i=n;i<=m;++i)tmp1=(tmp1+b[i])%p; printf("%lld\n",tmp1); return 0; }else{ for(Lint i=n;i<=k;++i)tmp2=(tmp2+b[i])%p; n=max(n,k+1LL); for(int i=1;i<=k;++i)t.e[1][i]=t.e[0][i]=c[i]; for(int i=2;i<=k;++i)t.e[i][i-1]=1; t.e[0][0]=1; Ksm(n-k-1); for(int i=1;i<=k;++i){ tmp1=(tmp1+ret.e[0][i]*b[k-i+1])%p; } tmp1=(tmp1+sum*ret.e[0][0])%p; t.clear(); for(int i=1;i<=k;++i)t.e[1][i]=t.e[0][i]=c[i]; for(int i=2;i<=k;++i)t.e[i][i-1]=1; t.e[0][0]=1; Ksm(m-k); for(int i=1;i<=k;++i)tmp2=(tmp2+ret.e[0][i]*b[k-i+1]%p)%p; tmp2=(tmp2+sum*ret.e[0][0])%p; printf("%lld\n",(tmp2-tmp1+p)%p); return 0; } }
致歉:笔者已经意识到这是一篇几乎没有价值的文章,给您的阅读带来不好的体验,并且干扰了您的搜索环境,非常抱歉!