На форумі обговорюються лише питання, пов'язані з олімпіадою
Ви не зайшли.
"Книжная полка".
Очевидно, что как бы мы не ложили книги, всегда можно задать нумерацию по признаку "слева направо; если одинаково, то сверху вниз". То есть, при любом расположении книг, будет существовать М! перестановок.
Далее будем предполагать, что книги, которые лежат на боку, представляют собой "сборник". Будем рассматривать его как единый элимент. Так, если сборников будет К, то комбинаций их расположений будет С(K, M-К*(N-1)). Отсюда К находится в пределах 0..[M/N]. Сумма чисел комбинаций для всех целых К из этого отрезка будет количеством всевозможных положений книг.
Полученые два числа мы перемножаем и получаем ответ: М!*Е(С(K, M-К*(N-1))) для всех целых 0<=К<=[M/N].
Особенность: использование длинной арифметики.
"Жабы".
Ничего особого не придумал. По сути, поиск в ширину, но быстро работает и простой поиск многократным проходом по доске [0..100, 0..100].
var x2,y2,x1,y1,k,w,i,j:integer; a:array[-100..200,-100..200]of integer; b,c:array[0..10200]of integer; procedure q(x,y:integer); begin if a[x,y]<0then a[x,y]:=k;end; begin fillchar(a,sizeof(a),255); read(x1,y1,x2,y2); a[x1,y1]:=0;k:=0;w:=-1; while a[x2,y2]<0do begin inc(k);inc(w); for i:=0to 100do for j:=0to 100do if a[i,j]=w then begin q(i-1,2*i-j); q(i+1,2*i-j); q(2*j-i,j-1); q(2*j-i,j+1); q(i-1,2*i-j-2); q(i+1,2*i+2-j); q(2*j-2-i,j-1); q(2*j+2-i,j+1); end; end; for i:=-100to -1do fillchar(a[i],sizeof(a[i]),-1); for i:=101to 200do fillchar(a[i],sizeof(a[i]),-1); for i:=0to 100do begin for j:=-100to -1do a[i,j]:=-1; for j:=101to 200do a[i,j]:=-1; end; k:=a[x2,y2]; w:=k; while k>-1 do begin b[k]:=x2;c[k]:=y2;dec(k); if a[x2+1,2*x2-y2]=k then begin y2:=2*x2-y2; inc(x2);end else if a[x2-1,2*x2-y2]=k then begin y2:=2*x2-y2; dec(x2);end else if a[2*y2-x2,y2+1]=k then begin x2:=2*y2-x2; inc(y2);end else if a[2*y2-x2,y2-1]=k then begin x2:=2*y2-x2; dec(y2);end else if a[x2+1,2*x2+2-y2]=k then begin y2:=2*x2+2-y2;inc(x2);end else if a[x2-1,2*x2-2-y2]=k then begin y2:=2*x2-2-y2;dec(x2);end else if a[2*y2+2-x2,y2+1]=k then begin x2:=2*y2+2-x2;inc(y2);end else begin x2:=2*y2-2-x2;dec(y2);end; end; writeln(w+1); for k:=0to w do writeln(b[k],' ',c[k]); end.
Поза форумом
"Разные цифры".
Вычисляем количество цифр в нужном числе, каким по счету является наименьшее из чисел такой же длины и каким после него является нужное число. Далее делаем простой перебор чисел.
const z:array[1..11]of longint=(1,10,91,739,5275,32491,168571,712891,2345851,5611771,8877691); var m,n:longint; c,i,k:shortint; q:boolean; a:array[1..10]of byte; b:array[-1..10]of boolean; begin read(m);n:=10; fillchar(b,sizeof(b),false); while m<z[n]do dec(n); if m*2<z[n]+z[n+1] then {!!!!!!!!!} .... begin m:=m-z[n]; a[n]:=1; b[1]:=true; a[n-1]:=0; b[0]:=true; for i:=n-2downto 1do begin a[i]:=n-i;b[n-i]:=true; end; while m>0do begin k:=1; q:=false; repeat c:=a[k]+1; while b[c]do inc(c); if c=10then begin b[a[k]]:=false; inc(k); end else begin b[a[k]]:=false; b[c]:=true; a[k]:=c; c:=0; for i:=k-1downto 1do begin while b[c]do inc(c); a[i]:=c; b[c]:=true; inc(c); end; q:=true; end; until q; dec(m); end; for i:=n downto 1do write(a[i]); end; ...
При N=1 ответом будет вводимое число. При N=10 делаем то же самое, что и при N=9, а последняя цифра равна разности 45 и суммы остальных чисел.
Особенность: при таком подходе не проходят по времени два теста. Посему делается проверка {!!!!!!!!!}, чтобы определить к какому из чисел (1023... или 9876...) нужное число ближе. Код написан для близости к 1023... . Для более эффективной работы пишется аналогичный дополнительный кусок перебора от 9876...
Поза форумом
"Разные цифры":
Определив длину числа не обязательно осуществлять полный перебор (потому и таймлимит). Зная кол-во чисел с разными цифрами и длиной на один меньше определяется отдельно каждая цифра искомого числа:
program diferentdigits; type sof=set of 0..9; var i,n,l,j,q,s:longint; r:sof; function size(r:sof):longint; var s:longint; i:0..9; begin s:=0; for i:=0 to 9 do if (i in r) then s:=s+1; size:=s; end; function cnt_lng(l:longint;r:sof):longint; var i,j,s:longint; begin if l<=0 then begin cnt_lng:=1; exit; end; i:=2; s:=size(r-[0]); j:=size(r)-1; while (i<=l) and (j>0) do begin i:=i+1; s:=s*j; j:=j-1; end; cnt_lng:=s; end; function cnt_lng0(l:longint;r:sof):longint; var i,j,s:longint; begin if l<=0 then begin cnt_lng0:=1; exit; end; i:=2; s:=size(r); j:=size(r)-1; while (i<=l) and (j>0) do begin i:=i+1; s:=s*j; j:=j-1; end; cnt_lng0:=s; end; begin read(n); l:=0; s:=0; while s<n do begin l:=l+1; s:=s+cnt_lng(l,[0..9]); end; s:=s-cnt_lng(l,[0..9]); r:=[0..9]; n:=n-s; for i:=1 to l do begin j:=0; if i=1 then j:=1; while not (j in r) do j:=j+1; q:=cnt_lng0(l-i,r-[j]); while n>q do begin repeat j:=j+1; until j in r; n:=n-cnt_lng0(l-i,r-[j]); end; write(j); r:=r-[j]; end; writeln; end.
Поза форумом
"Книжная полка"
Еще один вариант: пусть все книги одинаковы. Тогда на каждом конкретном шагу мы можем положить либо одну книгу вертикально либо N горизонтально - а это уже рекурентное соотношение f(i)=f(i-1)+f(i-n). Ответом к задаче будет M!*f(M)
program bookshelf; const ml=500; type bn=array [0..ml] of byte; var v,u:bn; m,n,i:longint; s:array[0..100] of bn; function sign(x:longint):shortint; begin if x=0 then sign:=0 else if x>0 then sign:=1 else sign:=-1; end; function max(a,b:longint):longint; begin if a>b then max:=a else max:=b; end; procedure writebn(a:bn); var i:word; begin for i:=a[0] downto 1 do write(a[i]); end; procedure setbn(var a:bn; x:longint); var i,p:longint; begin fillchar(a,sizeof(a),0); p:=x; i:=1; repeat a[i]:=p mod 10; p:=p div 10; i:=i+1; until p=0; a[0]:=i-1; end; procedure sumbn(a,b:bn; var c:bn); var i,p:word; begin setbn(c,0); i:=1; p:=0; while ((i<=a[0]) or (i<=b[0])) or (p<>0) do begin c[i]:=(a[i]+b[i]+p) mod 10; p:=(a[i]+b[i]+p) div 10; i:=i+1; end; c[0]:=i-1; end; function mlbn(a,b:bn):shortint; var i:word; q:shortint; begin q:=sign(a[0]-b[0]); i:=max(a[0],b[0]); while (q=0) and (i>=1) do begin q:=sign(a[i]-b[i]); i:=i-1; end; mlbn:=q; end; procedure mulln(a:bn; k:longint; var b:bn); var i,p:word; begin setbn(b,0); i:=1; p:=0; while (i<=a[0]) or (p<>0) do begin b[i]:=(a[i]*k+p) mod 10; p:=(a[i]*k+p) div 10; i:=i+1; end; b[0]:=i-1; end; function findlng(a:bn):word; var i:word; begin i:=ml; while a[i]=0 do i:=i-1; findlng:=max(i,1); end; procedure mulbn(a,b:bn; var c:bn); var i,j,p:word; q,z:bn; begin setbn(q,0); for i:=1 to a[0] do begin setbn(z,0); mulln(b,a[i],z); for j:=z[0] downto 1 do z[j+i-1]:=z[j]; for j:=i-1 downto 1 do z[j]:=0; z[0]:=z[0]+i-1; sumbn(z,q,q); end; c:=q; c[0]:=findlng(c); end; procedure fact(n:longint; var f:bn); var i:longint; begin setbn(f,1); for i:=2 to n do mulln(f,i,f); end; begin readln(m,n); setbn(s[0],1); for i:=1 to m do if i<n then s[i]:=s[i-1] else sumbn(s[i-1],s[i-n],s[i]); fact(m,v); mulbn(v,s[i],u); writebn(u); end.
Поза форумом
Subway
Два основных момента задачи:
- ответом будет минимум из всех расстояний между всеми точками первого (второго) многоугольника и отрезками второго (первого)
- собственно нахождение расстояния между точкой и отрезком (s):
формула для нахождения расстояния между точкой и прямой (d) в принципе известна: d=(a*x0+b*y0+c)/sqrt(a*a+b*b)
(a,b,c - параметры прямой; x0,y0 - координаты точки). Это расстояние - длина перпендикуляра опущеного с даной точки на даную прямую. Но он то может и не попасть на отрезок. Поэтому найдем расстояние от даной точки до начала (d1), середины (d2) и конца (d3) даного отрезка. Если d1<d2<d3 то перпендикуляр попадет в точку "перед" началом отрезка искомое s=d1; если d1>d2>d3 то перпендикуляр попадет в точку "за" концом отрезка искомое s=d3; если же d1>=d2<=d3, то наш перпендикуляр "попадает" в отрезок и s=d
{$Q-,R-,S-} program subway; type pnt=record x,y:real; end; line=record a,b,c:real; p1,p2:pnt; end; plnm=record n:integer; a:array[1..100] of pnt; end; var p1,p2:plnm; i,j,k:longint; l:line; ans,nans:real; ps,pf,aps,apf:pnt; procedure points2line(p1,p2:pnt; var l:line); var q:real; begin l.p1:=p1; l.p2:=p2; l.a:=p2.y-p1.y; l.b:=p1.x-p2.x; l.c:=-p1.y*l.b-p1.x*l.a; q:=sqrt(sqr(l.a)+sqr(l.b)); l.a:=l.a/q; l.b:=l.b/q; l.c:=l.c/q; end; function dst(p1,p2:pnt):real; begin dst:=sqrt(abs(sqr(p1.x-p2.x)+sqr(p1.y-p2.y))); end; procedure line_line(l1,l2:line;var p:pnt); begin p.x:=(l1.b*l2.c-l1.c*l2.b)/(l1.a*l2.b-l1.b*l2.a); p.y:=(l1.a*l2.c-l1.c*l2.a)/(l1.b*l2.a-l1.a*l2.b); end; function dst_pntline(p:pnt;l:line;var ps,pf:pnt):real; var d1,d2,d,ds:real; s:pnt; lp:line; begin d1:=dst(p,l.p1); d2:=dst(p,l.p2); s.x:=(l.p1.x+l.p2.x)/2; s.y:=(l.p1.y+l.p2.y)/2; ds:=dst(p,s); d:=abs(l.a*p.x+l.b*p.y+l.c); ps:=p; if (d1>=ds) and (ds<=d2) then begin dst_pntline:=d; lp.a:=-l.b; lp.b:=l.a; lp.c:=-p.y*lp.b-p.x*lp.a; line_line(l,lp,pf); end; if (d1<ds) and (ds<d2) then begin dst_pntline:=d1; pf:=l.p1; end; if (d1>ds) and (ds>d2) then begin dst_pntline:=d2; pf:=l.p2; end; end; begin readln(p1.n); for i:=1 to p1.n do read(p1.a[i].x,p1.a[i].y); readln(p2.n); for i:=1 to p2.n do read(p2.a[i].x,p2.a[i].y); ans:=MaxLongint; for i:=1 to p1.n do for j:=1 to p2.n do for k:=j+1 to p2.n do begin points2line(p2.a[j],p2.a[k],l); nans:=dst_pntline(p1.a[i],l,ps,pf); if nans<ans then begin ans:=nans; aps:=ps; apf:=pf; end; end; for i:=1 to p2.n do for j:=1 to p1.n do for k:=j+1 to p1.n do begin points2line(p1.a[j],p1.a[k],l); nans:=dst_pntline(p2.a[i],l,ps,pf); if nans<ans then begin ans:=nans; aps:=ps; apf:=pf; end; end; writeln(aps.x:3:3,' ',aps.y:3:3); writeln(apf.x:3:3,' ',apf.y:3:3); end.
Відредаговано redman17 (2008-10-18 15:31:40)
Поза форумом
Frogs
действительно самый простой вариант - поиск в ширину:
{$B-,Q-,R-,S-} program frogs; const max_dp=101*101+1; type longint=0..max_dp; var a0,b0,a,b,x,y,u,i,a1,b1:longint; r:array[0..100,0..100] of boolean; h,t:longint; dp:array[1..max_dp,1..3] of longint; p:array[1..max_dp,1..2] of longint; procedure put(x,y:longint); begin if (x>=0) and (x<=100) and (y>=0) and (y<=100) and (not r[x,y]) then begin dp[t,1]:=x; dp[t,2]:=y; dp[t,3]:=h; t:=t+1; r[x,y]:=true; end; end; begin read(a0,b0,a,b); h:=1; t:=2; dp[1,1]:=a0; dp[1,2]:=b0; dp[1,3]:=0; r[a0,b0]:=true; while not r[a,b] do begin a1:=dp[h,1]; b1:=dp[h,2]; x:=2*b1-a1; y:=b1+1; put(x,y); y:=b1+1; x:=2*y-a1; put(x,y); x:=2*b1-a1; y:=b1-1; put(x,y); y:=b1-1; x:=2*y-a1; put(x,y); y:=2*a1-b1; x:=a1+1; put(x,y); x:=a1+1; y:=2*x-b1; put(x,y); y:=2*a1-b1; x:=a1-1; put(x,y); x:=a1-1; y:=2*x-b1; put(x,y); h:=h+1; end; u:=t+1; while (dp[u,1]<>a) or (dp[u,2]<>b) do u:=u-1; y:=1; p[1,1]:=a; p[1,2]:=b; u:=dp[u,3]; while u<>0 do begin y:=y+1; p[y,1]:=dp[u,1]; p[y,2]:=dp[u,2]; u:=dp[u,3]; end; writeln(y); for i:=y downto 1 do writeln(p[i,1],' ',p[i,2]); end.
Поза форумом