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 Input0 1 1 10
10000 Sample Output89
113 HINT0 < = 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.