| ||||||||||
| Online Judge | Problem Set | Authors | Online Contests | User | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest | |||||||||
表示这题DP 30行搞定,不会排列组合也能做。f[i,j]表示二进制下一共i位,有j位是0的数的个数。
d[i,j]表示二进制下一共i位,有>=j位是0的数的个数。
求区间[s,e]的RoundNumber可以转化[1,e+1)-[1,s)
设某数s在二进制下有a位,则1~a-1位的数很容易计算:
∑d[i-1,(i+1)/2](1<=i<=a-1),其中第一位必须是1。
下面就是计算a位中比s小的符合要求的数:
若s上某一位是1(除了第一位),这一位前面已经有k个0,后边还有j位,
可以把这一位变成0,这样前面有k+1个0,
后边需要的0的个数至少为temp=max(0,(a+1)/2-k-1),所以inc(ans,d[j,temp])。
至此,该题用DP完美解决。
var
f,d:array[0..32,0..32]of int64;
s,e,a,b,i,j,k,ans:longint;
function calc(s,a:longint):longint;
begin
calc:=0;
for i:=1 to a-1 do inc(calc,d[i-1,(i+1)>>1]);
k:=0;
for i:=a-2 downto 0 do
if (s>>i)and 1=1 then
begin
j:=(a+1)>>1-k-1;
if j<0 then j:=0;
inc(calc,d[i,j]);
end
else inc(k);
end;
begin
for i:=0 to 31 do f[i,0]:=1;
for i:=1 to 31 do
for j:=1 to i do
f[i,j]:=f[i-1,j]+f[i-1,j-1];
d[0,0]:=1;
for i:=1 to 31 do
for j:=i downto 0 do
d[i,j]:=d[i,j+1]+f[i,j];
readln(s,e);
inc(e);
while s>>a<>0 do inc(a);
while e>>b<>0 do inc(b);
writeln(calc(e,b)-calc(s,a));
end.
Followed by:
Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator