Description
小 Z 最近遇上了大麻烦,他的数学分析挂科了。于是他只好找数分老师求情。
善良的数分老师答应不挂他,但是要求小 Z 帮助他一起解决一个难题问题是这样的,现在有 n 个标号为 1~n 的球和 m 个盒子,每个球都可以放进且只能放进一个盒子里面,但是要满足如下的规则:
- 若把标号为 i 的球放进了第 j 个盒子,那么标号为 2*i 的球一定要在第 j+1 个盒子里面(若 j<m)
- 若把标号为 i 的球放进了第 j 个盒子,并且 k*2=i,那么标号为 k 的球一定要在第 j-1 个盒子里面(若 j>1)
小 Z 的数分老师想要知道,给定了 n 和 m 的时候,第一个盒子最多能放进去多少个球。事实上,他已经推算出了公式,但是需要检验当 n 趋向于无穷大时是否仍然满足这个公式,因此 n 可能会非常大。
Input
本题包含多组数据,第一行为一个数(T<=20),表示数据组数;以下 T 行,每组数据一行,包括两个数 n 和 m。
Output
每组数据输出一行,包括一个数,即第一个盒子最多能放进多少个球。
Sample Input
2
10 2
10 3
Sample Output
4
1
Data Constraint
对于 10%的数据,n<=10^6
对于 20%的数据,n<=10^9
对于 30%的数据,m=2
对于 100%的数据,n<=10^10000,2<=m<=25
Hint
样例解释:
(1).{1,3,4,5}, {2,6,8,10}
(2).{1},{2},{4}
题解
坑题!!!!!
我用pascal卡常卡了近2小时卡过了,而C++一个臭氧就飞过去了
what a fine day
这道题知道结论+高精度/压位+卡常题。
首先我们考虑把某个数字放到第一位。
然而我们发现,这样放的话第2个limit是没用的。
我们就先来一个一个考虑——
依次放
依次放(然而这个情况与上面重复,舍去)
依次放
依次放(一样重复)
依次放
……
所以最终只有奇数是可以加入答案的。
上面什么意思呢?
由于当:满足时,这个奇数就是一种合法的放置方法。
所以求出奇数个数即可。
当然,放完这些后,这一段也是可以放入的。
于是我们再和上面类似的——
所以一直递归下去直到n=0时停止即可。
真是一道奇妙的结论题啊!
注意压位+卡常
代码
type
new=array[0..1200] of longint;
var
i,j,k,l,m,t,ii:longint;
p,q,op,ok:int64;
s,n:ansistring;
answer,nn,x1,c1,c0,c:new;
procedure chu(var n:new;di:longint);
var
p,yp:int64;
i,pp,ypp:longint;
begin
if di>1 then
begin
p:=0;
for i:=n[0] downto 1 do
begin
yp:=p;
p:=(int64(n[i]+p*1000000000) and ((1 shl di)-1));
n[i]:=int64(n[i]+yp*1000000000) shr di;
end;
end
else
begin
pp:=0;
for i:=n[0] downto 1 do
begin
ypp:=pp;
pp:=(int64(n[i]+pp*1000000000) and ((1 shl di)-1));
n[i]:=int64(n[i]+ypp*1000000000) shr di;
end;
end;
while (n[0]>1) and (n[n[0]]=0) do dec(n[0]);
end;
function plus(a,b:new):new;//inline;
var
ii,jj:longint;
begin
fillchar(c,sizeof(c),0);
if a[0]<b[0] then c[0]:=b[0]
else c[0]:=a[0];
for ii:=1 to c[0] do
begin
if c[ii]+a[ii]+b[ii]>1000000000 then
begin
c[ii+1]:=1;
c[ii]:=(c[ii]+a[ii]+b[ii])mod 1000000000;
end
else
c[ii]:=c[ii]+a[ii]+b[ii];
end;
while c[c[0]+1]=1 do
begin
inc(c[0]);
end;
exit(c);
end;
procedure insert(st:ansistring; var x:new);inline;
var
len:longint;
begin
len:=length(st);
while len>=9 do
begin
inc(x[0]);
val(copy(st,len-8,9),x[x[0]]);
dec(len,9);
end;
if len>0 then
begin
inc(x[0]);
val(copy(st,1,len),x[x[0]]);
end;
end;
procedure print(a:new);inline;
var
ii:longint;
begin
write(a[a[0]]);
for ii:=a[0]-1 downto 1 do
begin
if a[ii]<100000000 then write(0);
if a[ii]<10000000 then write(0);
if a[ii]<1000000 then write(0);
if a[ii]<100000 then write(0);
if a[ii]<10000 then write(0);
if a[ii]<1000 then write(0);
if a[ii]<100 then write(0);
if a[ii]<10 then write(0);
write(a[ii]);
end;
end;
begin
readln(t);
while t>0 do
begin
fillchar(c,sizeof(c),0);
dec(t);
readln(s);
fillchar(answer,sizeof(answer),0);
fillchar(nn,sizeof(nn),0);
n:='';
m:=0;
j:=0;
for i:=1 to length(s) do
begin
if (s[i]<>' ') and (j=0) then
begin
n:=n+s[i];
end
else
if s[i]=' ' then
begin
j:=1;
end
else
if (s[i]<>' ') and (j<>0) then
begin
m:=m*10+ord(s[i])-48;
end;
end;
c1[0]:=1;c1[1]:=1;
insert(n,nn);
chu(nn,m-1);
x1:=plus(nn,c1);
chu(x1,1);
answer:=plus(answer,x1);
while (nn[0]>1) or ((nn[0]=1) and (nn[1]>0)) do
begin
chu(nn,m);
x1:=plus(nn,c1);
chu(x1,1);
answer:=plus(answer,x1);
end;
print(answer);
writeln;
end;
end.
end.