Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Произведения (Delphi, Pascal)

10K
17 сентября 2007 года
ost-andrew
19 / / 24.01.2006
Задачу не решил. Ничего умнее перебора (с некоторыми ограничениями) не придумал, а он на 15-19 цифрах попросту зависает.

Текст задачи:
Имеется набор из N десятичных цифр (3<=N<=19). Требуется найти все возможные варианты равенства вида:
A * B = C,
где A, B и C – числа, составленные из этих цифр. В каждом примере умножения должны быть использованы все цифры набора, причем каждая – ровно один раз. Запись числа не может начинаться с цифры 0, за исключением числа ноль.

Входные данные:

Входной файл содержит строку – набор цифр без пробела.

Выходные данные:

Выходной файл должен содержать: в первой строке – количество всех возможных вариантов умножения, в каждой из последующих срок – числа А, В и С очередного варианта через пробел.

Примеры:
input.txt
771
output.txt
2
1 7 7
7 1 7

input.txt
2235
output.txt
0

input.txt
242424686868686
output.txt
2
246 26288 6466848
26288 246 6466848
276
17 сентября 2007 года
Rebbit
1.1K / / 01.08.2005
А можно поподробнее о твоих ограничениях в переборе ?
551
17 сентября 2007 года
Pavia
357 / / 22.04.2004
Отборочный тур завершился. Так, что могли решение опубликовать. Задачка на перебор с отсечением.
276
17 сентября 2007 года
Rebbit
1.1K / / 01.08.2005
Вот что мне в голову пришло....
Есть масив доступных цыфр (думаю у вас он тоже есть).

Снаружы перебор по первому множителю.
Внутри перебор по второму множителю но только с доступных цыфр (ведь при формировании первого числа кое что уже используется).

Самое важное - второй множитель формируем с конца по одной цыфре и при добавлении каждой новой цыфры второго множителя сразу получаем одну цыфру произведения (тоже с конца).
Так мы можем очень быстро усекать перебор по второму множителю.
Я понимаю что
Цитата:
Отборочный тур завершился

но хотелось бы добить ету задачу :). Очень уж она на мой взгяд интересная.

ЗЫ. Еще важно както определить верхнюю черту для перебора по первому множителю.
19! очень большое число и столько перебрать не получится, но оно нам и не надо. При некоторой розрядности первого множителя мы никогда не получим доступного произведения. Скажем при розрядности первого множителя в 10 цыфр нам просто не хватит цыфр для второго множителя и произведения. Но ету границу надо определить еще точнее.

ЗЫ 2. Посмотрел примеры. Отсюда мысль.
Первый множитель всегда больше второго должен быть. При переборе второго множителя если он становится больше первого - останавливаем перебор по второму. Если у нас все сошлось и множители разные - то выводим два варианта (во втором переставим множители местами)

261
17 сентября 2007 года
ahilles
1.5K / / 03.11.2005
я кстати тоже учавствовал в отборочном этапе. четыре часа думал над этой задачей так и не додумался (хорошо что хватило времени на первое и третье).
мне интересно: есть ли вообще тот кто сделал это задание?
при наборе размером в 14 цифр задача почти не решаема с помощью глупого перебора, поэтому нужнен умный перебор

ЗЫ. ещё одна мысль которая пришла мне в голову. сумма длин множителей не может быть длинее чем 2/3 длины всего набора

кстати все задания здесь
http://stud-olymp07.nm.ru/zad1etap_rezerv.htm
10K
17 сентября 2007 года
ost-andrew
19 / / 24.01.2006
На наборе цифр 00123456789 моя прога выдаёт 725840 результатов, время - 7.5 секунд (если выключить антивирус и брандмауер - 6.5 секунд), размер output.txt равен 10887608 байт. Допустим, что один из множителей и ответ равны 0, то второй множитель может принимать 9! вариантов (9! = 362880). Если учесть что множители можно менять местами, то 2*9! = 725760, что примерно равно 725840. Значит если взять input.txt с двумя нулями и 17 произвольных цифр (по возможности, чтобы повторений цифр был минимум) то количество результатов примерно равно 2*17!. У меня возникает вопрос: хватит ли места на винте, чтобы всё это сохранить? Это ж ппц какой винчестер нужен. В общем перебор, даже с ограничениями - сомнительный вариант. Пусть даже организаторы решили задачу имеено перебором, то я сомневаюсь, что их решение выведет правильный ответ, который занимает несколько Петабайтов...

Вот решение одного из знакомых. В его решении в ОЗУ они на этих исходных данных будут занимать именно столько, хотя с двумя или более 0 у меня уже на десяти цифрах не дождаться ответа, но при 19 с двумя 0 получается 17!*2*24=15 Пб. Хотя тут х3.

Код:
Program mult;

{$APPTYPE CONSOLE}

Uses
 Sysutils;

Type
 NA = Array [1..19] Of Integer;

Var
 S: String;
 lon: Integer;
 used, tempused: Set Of Byte;
 max: Integer;
 n, n2, R: Int64;
 minget, getted: Integer;
 A: Array [0..1000000] Of Record
                         A: Int64;
                                     B: Int64;
                                     C: Int64;
                        End;
 anmarr: Array[0..11,0..19] Of Int64;
 error: Integer;

Function GetLength(N: Int64): Integer;
 Begin
  result:=0;
  if n<10 then result:=1
  else
   if n<100 then result:=2
  else
   if n<1000 then result:=3
  else
   if n<10000 then result:=4
  else
   if n<100000 then result:=5
  else
   if n<1000000 then result:=6
  else
   if n<10000000 then result:=7
  else
   if n<100000000 then result:=8
  else
   if n<1000000000 then result:=9
  else
   if n<10000000000 then result:=10
  else
   if n<100000000000 then result:=11
  else
   if n<1000000000000 then result:=12
  else
   if n<10000000000000 then result:=13
  else
   if n<100000000000000 then result:=14
  else
   if n<1000000000000000 then result:=15
  else
   if n<10000000000000000 then result:=16
  else
   if n<100000000000000000 then result:=17
  else
   if n<1000000000000000000 then result:=18;
 End;

Function Anm(n, m: Integer): Int64;
Var
 I: Integer;
Begin
 Result:=1;
 For i:=m-n+1 To m Do
  Result:=Result*i;
End;

Function TenStp(st: Integer): Int64;
Begin
 result:=1;
 case st of
  0: result:=1;
  1: result:=10;
  2: result:=100;
  3: result:=1000;
  4: result:=10000;
  5: result:=100000;
  6: result:=1000000;
  7: result:=10000000;
  8: result:=100000000;
  9: result:=1000000000;
 10: result:=10000000000;
 11: result:=100000000000;
 12: result:=1000000000000;
 13: result:=10000000000000;
 14: result:=100000000000000;
 15: result:=1000000000000000;
 16: result:=10000000000000000;
 17: result:=100000000000000000;
 18: result:=1000000000000000000;
 end;
End;

Function GetNumber(A: NA; Count: Integer): Int64;
Var
 I: Integer;
 ten: Integer;
Begin
 Result:=0;
 ten:=1;
 if (s[a[1]]='0')and(count>1) then error:=1;
 For i:=count DownTo 1 do
  Begin
   Result:=Result+(Ord(S[a])-48)*Ten{stp(count-i)};
   ten:=ten*10;
  End;
End;

Function GetPer(Num, Count, Free: Integer): Int64;
Var
 A: NA;
 I, j, k, temp: Integer;
Begin
 error:=0;
 dec(num);
 temp:=free-count+1;
 k:=1;
 a[count]:=(num mod temp)+1;
 For i:=Count-1 Downto 1 Do
  Begin
   k:=k*(free-i);
   temp:=free-i+1;
   a:=((num div k) mod temp)+1;
  End;
 For i:=1 To count Do
  Begin
   k:=0;
   For j:=1 to lon Do
    if not (j in used) then
     Begin
      inc(k);
      if k=a then
       Begin
        a:=j;
        include(used, j);
        break;
       End;
     End;
  End;
  Result:=GetNumber(a, count);
End;

Procedure Sort(var S: String);
Var
 I, J, lon: Integer;
 ch: Char;
Begin
 lon:=Length(S);
 For i:=1 To lon-1 Do
  For j:=i+1 To lon Do
   Begin
    If s>s[j] Then
     Begin
      ch:=s;
      s:=s[j];
      s[j]:=ch;
     end;
   End;  
End;

Procedure Add(n, n2, r: Int64);
Var
 res: String;
 Bt: Set Of Byte;
 i, j: Integer;
Begin
 For i:=0 to getted-1 Do
  if ( ((n=a.A)and(n2=a.b)) or (n2=a.a))and(r=a.C) then exit;
 bt:=used;
 res:=IntToStr(r);
 Sort(res);
 j:=1;
 For i:=1 To Lon Do
  Begin
   if not (i in bt) then
    if res[j]<>s then exit else inc(j);
  End;
 if n=n2 then inc(minget);
 a[getted].a:=n;
 a[getted].b:=n2;
 a[getted].c:=r;
 inc(getted);
End;

Var
 i, j, k, l: Int64;
 c: Integer;
 F: TextFile;
Begin
 I:=0;
 While i<=11 Do
  Begin
   j:=0;
   While j<=19 Do
    Begin
     anmarr[i, j]:=anm(i, j);
     inc(j);
    End;
   inc(i);
  End;
 AssignFile(F, 'input.txt');
 Reset(F);
 ReadLn(F, S);
 CloseFile(F);
 lon:=Length(s);
 Sort(S);
 getted:=0;
 minget:=0;
 max:=lon div 3;
 i:=1;
 While i<=max Do
  Begin
   j:=1;
   While j<=anmarr[i, lon] Do
    Begin
     used:=[];
     n:=getper(j, i, lon);
     if (n=0) Then
      if (j<>1)or(pos('00',s)=0 )then
       begin
        inc(j);
        continue;
       end;
     if error<>0 then begin inc(j); continue; end;
     if n=0 then used:=[1,2];
     tempused:=used;
     if n=0 then
      Begin
       l:=1;
       While l<=anmarr[lon-2, lon] Do
        Begin
           used:=tempused;
           n2:=getper(l, lon-2, lon);
           if n2=0 then begin inc(l); continue; end;
           if error<>0 then begin inc(l);continue; end;
           Add(0, n2, 0);
           inc(l);
        End;
      End
     Else
      Begin
       k:=1;
       While k<=(lon-i-1) Do
        Begin
         if getlength(n*(tenstp(k)-1))<(lon-i-k) then Begin inc(k); continue end else
          if getlength(n*tenstp(k-1))>(lon-i-k) then break;
         l:=1;
         While l<=anmarr[k, lon] Do
          Begin
           used:=tempused;
           n2:=getper(l, k, lon-i);
           if n2=0 then begin inc(l); continue; end;
           if error<>0 then begin inc(l);continue; end;
           r:=n*n2;
           if getlength(r)>(lon-i-k) then break;
           if getlength(r)=(lon-i-k) then
           Add(n, n2, r);
           inc(l);
          End;
         inc(k);
        End;
      End;
     inc(j);
    End;
   inc(i);
  End;
 AssignFile(F, 'output.txt');
 Rewrite(F);
 WriteLn(F, getted*2-minget);
 For c:=0 To getted-1 Do
  Begin
   Writeln(f, a[c].a, ' ', a[c].b, ' ', a[c].c);
   if a[c].a<>a[c].b then
    Writeln(f, a[c].b, ' ', a[c].a, ' ', a[c].c);
  End;
 CloseFile(F);
end.
276
18 сентября 2007 года
Rebbit
1.1K / / 01.08.2005
Цитата: ost-andrew
хотя с двумя или более 0 у меня уже на десяти цифрах не дождаться ответа, но при 19 с двумя 0 получается 17!*2*24=15 Пб. Хотя тут х3.


Да-да. Некоректненько поставлено задание :)
Хотя я так прикинул, что мой алгоритм описаный выше (если откинуть возможность того что произведение может = 0) будет роботать за вполне приемлимое время.
На счет Замечания ахилеса про 2/3 от количества цыфр - в моем алгоритме при формировании второго множителя и результата с конца (а делается ето паралельно) ето ограничение уже само собой учитывается.

Ребята, а где соревнование то было ? На топкодере ?

261
18 сентября 2007 года
ahilles
1.5K / / 03.11.2005
Мне кажется организаторы сами не поняли какое задание дали, либо что-то неправильно рассчитали.
Цитата: Rebbit
Ребята, а где соревнование то было ? На топкодере ?


я же сказал: вот здесь оно было
http://stud-olymp07.nm.ru/

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог