两道与二进制有关的sequence
题目(第四题第五题)
题目有两个操作,x/2和x-1,很容易就想到和二进制有关,但具体关系是什么呢。
可以考虑x/2和x-1都是左移的操作,于是就可以发现X开头的有趣数列中的数都是x的二进制前缀。
例如 111 110 11 10 1 0
那么判断[a,b]中的有趣数列是不是含有k,只需要把k当做前缀然后取和区间[a,b]相交的部分就可以了。
这个程序写得好丑= =。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 program Neayo; 2 const 3 inf='sequence.in'; 4 ouf='sequence.out'; 5 var 6 i,j,t:longint; 7 k,a,b,ans,kk:int64; 8 function min(a,b:int64):int64; 9 begin 10 if a<b then exit(a) else exit(b); 11 end; 12 procedure init; 13 begin 14 assign(input,inf);assign(output,ouf); 15 reset(input);rewrite(output); 16 readln(t); 17 for t:=1 to t do 18 begin 19 readln(k,a,b); 20 ans:=0; 21 if k>=b then 22 begin 23 if k>b then writeln(0) else writeln(1); 24 continue; 25 end; 26 if k=0 then 27 begin 28 writeln(b-a+1); 29 continue; 30 end; 31 if k>=a then 32 begin 33 a:=k; 34 inc(ans); 35 if (not odd(k))and(k+1<=b)then inc(ans); 36 end; 37 kk:=k; 38 if not odd(kk) then 39 begin 40 kk:=kk+1; 41 if (kk>=a)and(k<a) then inc(ans); 42 end; 43 while k<b do 44 begin 45 k:=k shl 1; 46 kk:=(kk shl 1)+1; 47 if k>b then break; 48 if k>=a then ans:=ans+min(kk,b)-k+1; 49 if (k<a)and(kk>=a) then ans:=ans+min(kk,b)-a+1; 50 end; 51 writeln(ans); 52 end; 53 close(input); 54 end; 55 begin 56 init; 57 close(output); 58 end.
乍一看和上一道题好像。。。
贪心地分析可发现至少需要减max次(max为初始序列中最大的数),至多也只要减max次。因为如果把最大的数*2的话显然会增多很多次数。
于是有这样一个性质x-a/y-a是随着a的增大而减小的,那么对于那些x/max>1/2的数字,总会有个时候使x-a/max-a=1/2,那么我们只需要对它们*2就行了。
对于比max/2还要小的数,就先把它们变得比max/2大,再按照相同步骤处理。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
program Neayo; const inf='sequence.in'; ouf='sequence.out'; var i,j,k,n:longint; max,ans:int64; half,tmp:extended; a:array[0..200001]of int64; procedure init; begin assign(input,inf);assign(output,ouf); reset(input);rewrite(output); readln(n); for i:=1 to n do begin readln(a[i]); if a[i]>max then max:=a[i]; end; tmp:=max;half:=tmp/2; for i:=1 to n do if a[i]<max then begin tmp:=a[i]; inc(ans); while tmp<half do begin tmp:=tmp*2; inc(ans); end; end; inc(ans,max); writeln(ans); close(input); end; begin init; close(output); end.