codevs4247 奇特的生物

来源:互联网 发布:阿尔库津战役知乎 编辑:程序博客网 时间:2024/04/20 16:16
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 }

 

0 0
原创粉丝点击