zoukankan      html  css  js  c++  java
  • BZOJ1265[AHOI2006]斐波卡契的兔子

    http://www.lydsy.com/JudgeOnline/problem.php?id=1265

    Description

    卡卡开始养兔子了!妈妈给他买了一对刚出生的兔子,卡卡了解到兔子的繁殖规律是这样的:才出生的一对兔子在一个月后将第一次生出一胎a对兔子,接着在出生后的二个月又将生出b对兔子,在第三个月和以后每个月都会繁殖c对兔子。(a <= b <= c) 由斐波纳契数列我们知道兔子的繁殖速度是很快的,然而卡卡有兔子一样多的好朋友,卡卡想在m个月后有k对兔子,以便分给他们的好友,他的愿望是否能够实现呢? [任务] 编写一个程序: 从输入文件中读入输入信息; 计算m个月后卡卡将有多少对兔子,设之为P; 计算如果m个月后卡卡要拥有至少k对兔子,那么开始时妈妈至少应该为卡卡购买多少对兔子,设之为Q; 将结果输出至输出文件。

    Input

    输入文件的第一行有4个正整数:a, b, c和m;而第二行则仅含一个正整数k。它们的含义见上文描述。

    Output

    你的程序将向输出文件输出两行,第一行是一个整数P而第二行是一个整数Q。

    Sample Input

    0 1 1 10
    10000

    Sample Output

    89
    113

    HINT

    0 < = a < = b < = c< = 100, 1 < = m < = 3 000, 1 < = k < = 10^ 6 000

    裸高精度,可压7位。

    第二问就是k除以第m天兔子数向上取整,为了防止TLE,我们用倍增法:

    先用O(N)时间计算出所有的2^i * Fm的值(记为t[i]),顺便计算出2^i,使2^i恰好大于等于Fm。记bigg为t[Maxi]-Fm,nowans=2^maxi

    接着从i-1到0依次bigg减去t[i](如果减去还能为非负的话),若能减去,则nowans减去2^i.最后2^i就是答案。

    这题卡常数非常紧,空间也要安排好。看程序吧。

    program p1265;
    
    //by htfy96 http://www.cnblogs.com/htfy/ htfy96@qq.com
    Const
     u:array[0..8] of longint=(1,10,100,1000,10000,100000,1000000,10000000,100000000);
     obit=7;
     bit=10000000;
    
    Type
     gjd=record
       len:longint;
       d:array[0..1600] of longint;
     end;
     
    Var
     a,b,c,m,i:longint;
     f:array[0..3] of gjd;
     k,one,o,ans,y,bigg:gjd;
     t:array[0..20000] of gjd;
     two:gjd;
     
    Function big(a,b:gjd):boolean;forward;
    Function small(a,b:gjd):boolean;forward;
    procedure print(P:gjd);forward;
    
    Function max(a,b:longint):longint;
      begin
      if a>b then exit(a) else exit(b);
    end;
    
    Procedure fopen;
      begin
      assign(input,'kacci.in');
      assign(output,'kacci.out');
      reset(input);
      rewrite(output);
    end;
    
    Procedure fclose;
      begin
      close(input);
      close(output);
    end;
    
    Procedure initgjd(var p:gjd;q:longint);
      begin
      fillchar(p.d,sizeof(p.d),0);
      p.len:=1;
      p.d[1]:=q;
    end;
    
    Function cheng(p:gjd;q:longint):gjd;
    var
     i,jw:longint;
      begin
      cheng:=p;
      jw:=0;
      for i:=1 to cheng.len do
        begin
        cheng.d[i]:=cheng.d[i]*q+jw;
        jw:=cheng.d[i] div bit;
        cheng.d[i]:=cheng.d[i] mod bit;
      end;
      if jw>0 then
        begin
        inc(cheng.len);
        cheng.d[cheng.len]:=jw;
      end;
    end;
    
    procedure AddP(var p1:gjd;p2:gjd);
    var
     i,jw:longint;
      begin
      p1.len:=max(p1.len,p2.len)+2;
      jw:=0;
      for i:=1 to p1.len do
        begin
        p1.d[i]:=p1.d[i]+p2.d[i]+jw;
        jw:=p1.d[i] div bit;
        p1.d[i]:=p1.d[i] mod bit;
      end;
      while (p1.len>1) and (p1.d[p1.len]=0) do dec(p1.len);
    end;
    
    Function add(p1,p2:gjd):gjd;
    var
     i,jw:longint;
      begin
      add.len:=max(p1.len,p2.len)+2;
      jw:=0;
      for i:=1 to add.len do
        begin
        add.d[i]:=p1.d[i]+p2.d[i]+jw;
        jw:=add.d[i] div bit;
        add.d[i]:=add.d[i] mod bit;
      end;
      for i:=add.len+1 to 1600 do add.d[i]:=0;
      while (add.len>1) and (add.d[add.len]=0) do dec(add.len);
    end;
    
    Function minus(p1,p2:gjd):gjd;
    var
     i:longint;
      begin
      minus:=p1;
     // if big(p2,p1) then begin print(p1);print(p2); writeln('overflow!');fclose;halt;end;
      for i:=1 to minus.len do
        begin
        minus.d[i]:=minus.d[i]-p2.d[i];
        if minus.d[i]<0 then
          begin
          inc(minus.d[i],bit);
          dec(minus.d[i+1],1);
        end;
      end;
      while (minus.len>0) and (minus.d[minus.len]=0) do dec(minus.len);
    end;
    
    Procedure print(P:gjd);
    var
     i:longint;
      begin
      //writeln('len=',p.len);
      for i:=p.len downto 1 do
        if i=p.len then write(p.d[i]) else
          begin
          if p.d[i]<10 then write(0);
          if p.d[i]<100 then write(0);
          if p.d[i]<1000 then write(0);
          if p.d[i]<10000 then write(0);
          if p.d[i]<100000 then write(0);
          if p.d[i]<1000000 then write(0);
          write(p.d[i]);
        end;
      writeln;
    end;
    
    procedure readgjd(var p:gjd);
    var
     ct,newct,w,i:longint;
     t:array[0..6003] of longint;
     c:char;
      begin
      fillchar(p.d,sizeof(p.d),0);
      p.len:=0;
      ct:=0;
      while not eoln do
        begin
        inc(ct);
        read(c);
        w:=ord(c)-ord('0');
        t[ct]:=w;
      end;
      for i:=ct downto 1 do
        begin
        newct:=ct-i+1;
        //writeln('i=',i,' newct=',newct,' t[i]=',t[i],' p.len=',(newct-1) div 4+1);
        p.len:=(newct-1) div obit+1;
        inc(p.d[p.len],t[i]*u[(newct-1) mod obit]);
      end;
    end;
    
    Function cheng(p1,p2:gjd):gjd;
    var
     i,j,jw:longint;
      begin
      cheng.len:=p1.len+p2.len;
      fillchar(cheng.d,sizeof(cheng.d),0);
      for i:=1 to p1.len do
        for j:=1 to p2.len do
          inc(cheng.d[i+j-1],p1.d[i]*p2.d[j]);
      jw:=0;
      for i:=1 to cheng.len do
        begin
        cheng.d[i]:=cheng.d[i]+jw;
        jw:=cheng.d[i] div bit;
        cheng.d[i]:=cheng.d[i] mod bit;
      end;
      while (cheng.len>1) and (cheng.d[cheng.len]=0) do dec(cheng.len);
    end;
    
    Function big(a,b:gjd):boolean;
    var
     i:longint;
      begin
      if a.len>b.len then exit(true);
      if a.len<b.len then exit(false);
      for i:=a.len downto 1 do
        begin
        if a.d[i]>b.d[i] then exit(true);
        if a.d[i]<b.d[i] then exit(false);
      end;
      exit(false);
    end;
    
    Function small(a,b:gjd):boolean;
    var
     i:longint;
      begin
      if a.len<b.len then exit(true);
      if a.len>b.len then exit(false);
      for i:=a.len downto 1 do
        begin
        if a.d[i]<b.d[i] then exit(true);
        if a.d[i]>b.d[i] then exit(false);
      end;
      exit(false);
    end;
    
    Function div2(P:gjd):gjd;
    var
     i,jw:longint;
      begin
      div2:=p;jw:=0;
      for i:=p.len downto 1 do
        begin
        div2.d[i]:=div2.d[i]+jw*bit;
        jw:=div2.d[i] mod 2;
        div2.d[i]:=div2.d[i] div 2;
      end;
      while (div2.len>1) and (div2.d[div2.len]=0) do dec(div2.len);
    end;
    
    Function divide:gjd;
    var
     i,now:longint;
      begin
      t[0]:=o;
      now:=0;
      initgjd(two,1);
      
      while small(t[now],k) do
        begin
        inc(now);
        t[now]:=Add(t[now-1],t[now-1]);
        two:=add(two,two);
      end;
      
      y:=t[now];
      ans:=two;
      bigg:=minus(y,k);
      for i:=now-1 downto 0 do
        begin
        two:=div2(two);
        if not small(bigg,t[i]) then
          begin
          bigg:=minus(bigg,t[i]);
          ans:=minus(ans,two);
        end;
      end;
      exit(ans);
    end;
      
    
      begin
      fopen;
    
      readln(a,b,c,m);
    
      initgjd(f[1],1);
      initgjd(f[2],a+1);
      initgjd(f[3],a*a+b+a+1);
    
      for i:=4 to m+1 do
        begin
        f[i mod 4]:=f[(i-1) mod 4];
        AddP(f[i mod 4],Cheng(minus(f[(i-1) mod 4],f[(i-2) mod 4]),a));
        AddP(f[i mod 4],Cheng(minus(f[(i-2) mod 4],f[(i-3) mod 4]),b));
        AddP(f[i mod 4],Cheng(f[(i-3) mod 4],c));
      end;
          
      print(f[(m+1) mod 4]);
      o:=f[(m+1) mod 4];
      readgjd(k);
      ans:=divide;
      print(ans);
      fclose;
    end.
    
  • 相关阅读:
    restful接口设计规范总结
    SSM框架中,配置数据库连接的问题
    Java通过mysql-connector-java-8.0.11连接MySQL Server 8.0遇到的几个问题
    浅谈Spring的PropertyPlaceholderConfigurer
    过滤器与拦截器的区别
    SpringMVC的拦截器(Interceptor)和过滤器(Filter)的区别与联系
    SpringMVC中使用Interceptor拦截器
    mybatis中模糊查询的使用以及一些细节问题的注意事项
    mybatis generator(MyBatis的逆向工程)
    mybatis-generator生成逆向工程两种方式
  • 原文地址:https://www.cnblogs.com/htfy/p/2803873.html
Copyright © 2011-2022 走看看