codevs4247 奇特的生物

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 }
原文地址:https://www.cnblogs.com/lidaxin/p/4932057.html