![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Помогите решить плиз... [D7, WinXP]
uzver.exe © (2005-12-14 11:49:00)Даны числа А, В, К (А,В - от 0 до 10^9 и К от 0 до 30)
Надо найти кол-во натур чисел между А и В
таких, что кол-во единиц в записи этих чисел равно К
Сразу приходит на ум решение в лоб - то есть перебором
var
a,b,i:longint;
k:byte;
n:byte;{number of "ones"}
function count_one(inp:longint):byte;
var
cnt:byte;
begin
cnt:=0;
while (inp<>0) do begin
inp:=(inp-1) and inp;
cnt:=cnt+1;
end;
count_one:=cnt;
end;
n:=0;
readln(a);
readln(b);
readln(k);
for i:=a to b do begin
if count_one(i)=k then begin
n:=n+1;
end;
end;
writeln('Result is: ',n);
Код работает приемлемо при В-А<1000000 Помогите оптимизировать его...
uzver.exe (2005-12-14 15:04:00) [21]Спасибо, Digitman © за такой развёрнутый ответ!
Но проблема моего кода не в функции Подсчета кол-ва, единиц
а в том, что по сути дела я перебираю все числа между А и В
и проверяю их:
подходят(if (GetBinaryOneCount(i)=k) then ...) - увеличиваю счетчик чисел,
а нет - то не увеличиваю
но если А=0 а В=1 000 000 000 то на выполнение уйдет слишком много времени(для ускорения я воообще отказался от дополнительной ф-и
и делаю подсчет единиц и проверку в теле одного цикла)
Может на ассемблере вставку сделать? хотя врятли это поможет - как сказал evvcom - я не там копаю.
MBo (2005-12-14 14:53:00) [22]
procedure TForm1.Button3Click(Sender: TObject);
var
NN, KK, A, B, BB, Cnt: Integer;
Stop: Boolean;
procedure Colex(n, k: Integer; J: DWord);
begin
if J > B then
Exit;
if n = 0 then begin
if J >= A then
Inc(Cnt)
end
else begin
if k < n then begin
J := J and not (1 shl (n - 1));
Colex(n - 1, k, J);
end;
if k > 0 then
Colex(n - 1, k - 1, J or (1 shl (n - 1)));
end;
end;
begin
KK := 10;
Cnt := 0;
A := 0;
B := 1048575;
BB := B;
NN := 0;
while BB > 0 do begin
Inc(NN);
BB := BB shr 1;
end;
if NN >= KK then
Colex(NN, KK, 0);
Caption := Format('От %d до %d - %d чисел, в дв. записи которых %d ед.',
[A, B, Cnt, KK]);
end;
evvcom (2005-12-14 14:44:00) [23]ниче не понял из твоих уточнений. Смотри комбинаторику. Допустим (на пальцах) у тебя А=0, В = 99, К=1. Тебя устраивают 01, 10, 12..19, 21, 31, ..., 91: итого 18 чисел. Теперь математически. У тебя двазнакоместа, на которых может размещаться всего однаединица, т.е. надо найти количество сочетаний 1 из 2 (так вроде это произносится, давно было). Получаешь ответ 2. Теперь на остальных местах может располагаться любая цифра кроме 1, т.е. 9 цифр. Итого 2*9=18.
Digitman (2005-12-14 14:33:00) [24]function Get BinaryOneCount(Value: dword): Integer;
begin
Result :=0;
while (Value > 0) do
begin
if Value mod 2= 1 then
Inc(Result);
Value := Value div 2;
end;
end;
function Get OctalOneCount(Value: dword): Integer;
begin
Result :=0;
while (Value > 0) do
begin
if Value mod 8= 1 then
Inc(Result);
Value := Value div 8;
end;
end;
function Get HexadecimalOneCount(Value: dword): Integer;
begin
Result :=0;
while (Value > 0) do
begin
if Value mod 16= 1 then
Inc(Result);
Value := Value div 16;
end;
end;
...
function Get Base/B>OneCount(Base: Integer; Value: dword): Integer;
begin
Result :=0;
while (Value > 0) do
begin
if Value mod Base= 1 then
Inc(Result);
Value := Value div Base;
end;
end;
...
uzver.exe (2005-12-14 14:26:00) [25]Пардон, не уточнил.
Даны числа в Десятичной системе А и В(1≤A≤B≤10^9)
Надо найти кол-во чисел между А и В(A≤Z≤B)
таких, что кол-во единиц в ДВОИЧНОЙ записи этих
чисел было равно некому числу К, заданному в условии(1≤K≤30)
Один из вариантов - свести задачу к нахождению всех
вариантов построения числа z из k слогаемых, каждый из которых
равен двойке в какой либо степени(причём каждый раз новой)
еще пытался воспользоваться замечательным свойством ряда
чисел, вырыжающих кол-во единиц в дв. записи ряда натуральных чисел:
0 1 1 2 1 2 2 3 1 2 2 3 2 3 3 4
0
0{0+1}
01{0+1}{1+1}
0112{0+1}{1+1}{1+1}{2+1}
01121223{0+1}{1+1}{1+1}{2+1}{1+1}{2+1}{2+1}{3+1}
таким образом:
0
01
0112
01121223
0112122312232334
но пока я зашел в тупик
Digitman (2005-12-14 12:47:00) [26]function GetDecimalOneCount(Value: dword): Integer;
begin
Result :=0;
while (Value > 0) do
begin
if Value mod 10 = 1 then
Inc(Result);
Value := Value div 10;
end;
end;
Digitman (2005-12-14 12:37:00) [27]
> в записи этих чисел
в задании следует явно уточнять систему (десятичная, двоичная, хренеричная и т.д.) ... несмотря на приведенный пример собственного кода ..
> кол-во единиц
каких "единиц"-то ?
десятеричных ? двоичных ? N-чных ?
evvcom (2005-12-14 12:17:00) [28]
> Помогите оптимизировать его
Да такое решение не оптимизируешь.
Мне первое, что приходит на ум, это решить эту задачу математически, а компьютер (программу) потом использовать только для того, чтобы посчитать результат полученной функции. Есть такая область в математике, комбинаторика называется, вот ее тебе и надо здесь применить.