[Selected by Shandong Province] Recursive Sequence (Version 2)
Time limit: 1 Sec Memory limit: 128 MB
Title description
A sequence of natural numbers is defined as follows:
Opposite i <= k: Ai = Bi
Opposite i> k: Ai = C1Ai-1 + C2Ai-2 + …… CkAi-k
Among them, Bj and Cj (1<=j<=k) are given natural numbers. Write a program, given a natural number m<=n, calculate Am+Am+1+……An, and output the value of the remainder of dividing it by the given natural number p.
enter
The first line is the natural number k
The second line includes k natural numbers b1, b2, ... bk.
The third line contains k natural numbers c1, c2,...ck.
The fourth line contains three natural numbers m, n, p.
Output
A positive integer, representing the value of (Am+Am+1+……An)%p
Sample input
2
1 1
1 1
2 10 10003
Sample output
142
prompt
For 100% test data: 1<=k<=15;1<=m<=n<=10^18
For 20% of the test data: 1<=k<=15;1<=m<=n<=10^6
For 30% of the test data: k=1; 1<=m<=n<=10^18
For all test data: 0<=b1,b2,……,bk,c1,c2,……,ck<=10^9;1<=p<=10^8.
answer
From the question, we can know that if the sum of A(m~n) is required, we can find s(n)-s(m-1) (prefix sum), so the key recurrence formula is obtained:
So we might as well set the initial matrix as [A1 A2 …… Ak Sk],
……
So the initial matrix is multiplied by the acceleration matrix of (k+1)*(k+1):
Because Ai=Bi(i≤k), it can become
and so
Use the fast power of two matrices to find Sn and Sm-1 respectively, subtract the two numbers, add p and then %p.
Note that n≤k and m-1≤k can only be calculated by force.
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int k;
ll n,m,p,Sum[20];
struct matrix{
int n,m;
ll c[20][20];
matrix(){memset(c,0,sizeof(c));n=m=0;}
matrix operator*(const matrix&a){
matrix r;r.n=n,r.m=a.m;
for(int i=1;i<=n;i++)
for(int j=1;j<=r.m;j++)
for(int l=1;l<=m;l++)r.c[i][j]=(r.c[i][j]+c[i][l]*a.c[l][j])%p;
return r;
}
matrix mpow(matrix a,ll b){
matrix rs;rs.n=rs.m=a.n;
for(int i=1;i<=rs.n;i++)rs.c[i][i]=1;
for(;b;b>>=1){
if(b&1)rs=rs*a;
a=a*a;
}
return rs;
}
}a,b;
int main()
{
scanf("%d",&k);
a.n=1;a.m=k+1;
b.n=b.m=k+1;
for(int i=1;i<=k;i++)scanf("%lld",&a.c[1][i]),Sum[i]=Sum[i-1]+a.c[1][i];
a.c[1][k+1]=Sum[k];
for(int i=k;i>=1;i--)scanf("%lld",&b.c[i][k]),b.c[i][k+1]=b.c[i][k];
scanf("%lld%lld%lld",&n,&m,&p);
for(int i=1;i<k;i++)b.c[i+1][i]=1;
b.c[k+1][k+1]=1;
ll x,y;
if(m>k){
matrix c=a*b.mpow(b,m-k);
y=c.c[1][k+1]%p;
}
else y=Sum[m]%p;
if(n-1>k){
matrix c=a*b.mpow(b,n-1-k);
x=c.c[1][k+1]%p;
}
else x=Sum[n-1]%p;
printf("%lld",(y-x+p)%p);
putchar('\n');
return 0;
}