4247 奇特的生物
题目描述 Description
科学家们最近发现了一种奇怪的生物,它们每天长大一岁,刚出生的宝宝为1岁,且它们的年龄没有上限。已知年龄为1 岁,2岁,3岁,……,k岁的个体具有生育能力,当年龄为i的具有生育能力的个体将长大一岁时会生下ai个1岁的幼崽。假设第一天只有一个年龄为1的幼 崽,现在科学家们想知道第x天年龄为y的个体有多少,但由于该物种增长速度太快,于是他们将这个任务交给了你。由于这个数可能很大,你需要对p取模。
输入描述 Input Description
输入数据第一行给定四个整数k,x,y,p。
第二行包括k个整数,第i个整数代表ai。
输出描述 Output Description
输出数据包含一行,表示第x天年龄为y的个体的数量对p取模后的结果。
样例输入 Sample Input
【样例输入 1】
3 3 1 1007
1 1 1
【样例输入 2】
3 6 2 1007
1 2 1
样例输出 Sample Output
【样例输出1】
2
【样例输出 2】
13
数据范围及提示 Data Size & Hint
【思路】
矩阵乘法。
可以总结出题目所述的转换规则如下:
|F1,F2,F3…Fk| => |a1*F1+a2*F2+…ak*Fk , F1,F2,…Fk-1|
原矩阵A:
|1,0,0,…0|
转换矩阵T:
|a1,1,0,0…|
|a2,0,1,0…|
|.. , ..,..1…|
|ak,0,0 0…|
分类讨论(标号从0开始):
如果y>x 转移不到数目为0
否则
如果y<=k A=A*(T^(x-1))输出A[0][y-1]
否则
A=A*(T^(x-y+k)) 输出A[0][k-1]
(注意到只要是年龄比k大数目就不会发生变化,所以只要把y所对应的计算到k-1即可)
又:其实只要是1岁以后数目都不会发生变化,上述麻烦了。
【代码】
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 5 typedef long long LL; 6 const int maxn = 30+5; 7 LL k,x,y,m; 8 LL a[maxn]; 9 10 LL multi( LL y , LL cnt ) { 11 if ( ! cnt ) return 0 ; 12 if ( cnt == 1 ) return y % m ; 13 LL rec = multi( y , cnt / 2 ) ; 14 rec = ( rec + rec ) % m ; 15 if ( cnt % 2 ) rec = ( rec + y ) % m ; 16 return rec ; 17 } 18 struct Matrix{ 19 int r,c; 20 LL N[maxn][maxn]; 21 void init(int r,int c) { 22 this->r=r, this->c=c; 23 memset(N,0,sizeof(N)); 24 } 25 Matrix operator*(Matrix& B)const{ 26 Matrix C; 27 C.init(r,B.c); 28 for(int i=0;i<C.r;i++) 29 for(int j=0;j<C.c;j++) 30 { 31 for(int k=0;k<c;k++) C.N[i][j] += multi(N[i][k],B.N[k][j]); 32 C.N[i][j]%=m; 33 } 34 return C; 35 } 36 Matrix pow(LL p) { 37 Matrix tmp=*this; 38 Matrix ans; 39 ans.init(r,r); 40 for(int i=0;i<r;i++) ans.N[i][i]=1; 41 while(p) { 42 if(p&1) ans=ans*tmp; 43 tmp=tmp*tmp; 44 p>>=1; 45 } 46 return ans; 47 } 48 }A,T; 49 50 int main() { 51 scanf("%lld%lld%lld%lld",&k,&x,&y,&m); 52 for(int i=0;i<k;i++) scanf("%lld",&a[i]); 53 if(y>x) { 54 printf("0"); 55 return 0; 56 } 57 A.init(1,k); 58 A.N[0][0]=1; 59 T.init(k,k); 60 for(int i=0;i<k;i++) T.N[i][0]=a[i]; 61 for(int i=1;i<k;i++) T.N[i-1][i]=1; 62 if(y<=k) 63 { 64 T=T.pow(x-1); 65 A=A*T; 66 printf("%lld ",A.N[0][y-1]); 67 }else { 68 x=x-y+k; 69 T=T.pow(x-1); 70 A=A*T; 71 printf("%lld",A.N[0][k-1]); 72 } 73 return 0; 74 }