zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    python 包管理工具 pip 的配置
    Python 变量作用域 LEGB (下)—— Enclosing function locals
    Python 变量作用域 LEGB (上)—— Local,Global,Builtin
    2020 Java 面试题 小结 (答案慢慢补上,有错误请指出)
    mysql 根据日期(date)做年,月,日分组统计查询
    jvm指令
    正则表达式 分割地址 获取省市区详细地址
    .Net 异常记录
    WCF设计服务协议(一)
    plsql ORA-01789:查询块具有不正确的结果列数
  • 原文地址:https://www.cnblogs.com/lidaxin/p/4932057.html
Copyright © 2011-2022 走看看