На форумі обговорюються лише питання, пов'язані з олімпіадою
Ви не зайшли.
Итак у меня:
WOOD - 40
DSP - 34 - перестарался где-то
BUILDING - 40
PRIMENUM -38 - ну очень обидно
COUNTRY - 40
За первый тур 88 / 100
За второй тур 192 / 200
Всего 280 / 300
По-моему, неплохо, хотя глюки очень тупые...
Поза форумом
Публикую заодно решения задач, в которых у меня полный бал:
WOOD:
var N, Top, topl, topr, i, l, r : Integer; A : array [1..500] of record x,y,l : extended; end; TL, ML, SML, NL, MH, Len, ro, dl, dr : extended; isl : Boolean; begin Read(N); top := 1; TL := 0; for i := 1 to N do begin Read(A[i].X, A[i].Y); if i <> 1 then begin if A[i].Y > A[i-1].Y then top := i; A[i-1].l := sqrt(sqr(A[i].x-A[i-1].x)+sqr(A[i].y-A[i-1].y)); TL := TL+A[i-1].l; end; end; Read(ro); Len := sqrt(sqr(A[1].x-A[N].x)+sqr(A[1].y-A[N].y)); TL := (TL+Len)*ro; topl := top; while (topl > 1) and (A[topl-1].Y = A[topl].Y) do Dec(topl); topr := top; while (topr < N) and (A[topr-1].Y = A[topr].Y) do Inc(topr); l := 1; r := n; ML := Len; while (l < topl) and (r > topr) do begin SML := ML; dl := A[l+1].Y-A[l].Y; dr := A[r-1].Y-A[r].Y; if A[l+1].Y <= A[r-1].Y then begin MH := A[l+1].Y; isl := True; ML := ML+A[l].l; NL := ML+A[r-1].l*(MH-A[r].Y)/dr; end else begin isl := False; MH := A[r-1].Y; ML := ML+A[r-1].l; NL := ML+A[l].l*(MH-A[l].Y)/dl; end; if NL >= TL then begin MH := ( dr*dl*(TL-SML) + dr*A[l].Y*A[l].l + dl*A[r].Y*A[r-1].l )/ (dr*A[l].l + dl*A[r-1].l); Break; end; if isl then Inc(l) else Dec(r); end; WriteLn(MH); end.
BUILDING:
var M, N, i, j, l, t, C, max : Integer; A : array [1..100, 1..100] of Integer; begin Read(M, N); for i := 1 to M do begin C := 0; for j := 1 to N do begin Read(t); if t = 0 then C := 0 else Inc(C); A[i, j] := C; end; end; max := 0; for j := 1 to N do begin for i := 1 to M do if (A[i, j] <> 0) then if ((i = 1) or (A[i, j] > A[i-1, j])) then begin l := i; t := maxint; C := 0; while (l <= M) and (A[l, j] <> 0) do begin Inc(C); if A[l, j] < t then t := A[l, j]; if c*t > max then max := c*t; Inc(l); end; end; end; WriteLn(max); end.
COUNTRY:
var M : array [1..50000] of Byte; N, K, t, i, j : longint; A : array [1..3] of longint; C : array [1..3, 1..3] of longint; begin Read(N); FillChar(C, sizeof(C), 0); FillChar(A, Sizeof(A), 0); for i := 1 to N do begin Read(M[i]); Inc(A[M[i]]); end; for i := 1 to A[1] do if M[i] <> 1 then Inc(C[1, M[i]]); for i := A[1]+1 to N-A[2] do if M[i] <> 3 then Inc(C[3, M[i]]); for i := N-A[2]+1 to N do if M[i] <> 2 then Inc(C[2, M[i]]); K := 0; t := C[1, 2]; if C[2, 3] < t then t := C[2, 3]; if C[3, 1] < t then t := C[3, 1]; K := K+t; C[1, 2] := C[1, 2]-t; C[2, 3] := C[2, 3]-t; C[3, 1] := C[3, 1]-t; t := C[1, 3]; if C[3, 2] < t then t := C[3, 2]; if C[2, 1] < t then t := C[2, 1]; K := K+t; C[1, 3] := C[1, 3]-t; C[3, 2] := C[3, 2]-t; C[2, 1] := C[2, 1]-t; for i := 1 to 3 do for j := i+1 to 3 do begin t := C[i, j]; if C[j, i] < t then t := C[j, i]; K := K+t; C[i, j] := C[i, j]-t; C[j, i] := C[j, i]-t; end; WriteLn(K); end.
Поза форумом
Короче в мене 200/200. Ось розвязки
Building. Ну дуже жалко що розвязки O(N^3) проходять
const con=200; type t=word; var a:array[1..con] of T; stek:array[1..con] of T; max,c,n,m,i,j,size:T; q1,q2:array[1..con] of T; procedure read_data; begin read(n,m); for i:=1 to n do begin for j:=1 to m do begin read(c); a[j]:=(a[j]+1)*c; end; {lower bound} size:=0; for j:=m downto 1 do begin while (size<>0) and (a[j]<a[stek[size]]) do begin q1[stek[size]]:=j+1; dec(size); end; inc(size);stek[size]:=j; end; for j:=1 to size do q1[stek[j]]:=1; {upper bound} size:=0; for j:=1 to m do begin while (size<>0) and (a[j]<a[stek[size]]) do begin q2[stek[size]]:=j-1; dec(size); end; inc(size);stek[size]:=j; end; for j:=1 to size do q2[stek[j]]:=m; {compute answer} for j:=1 to m do if max<(q2[j]-q1[j]+1)*a[j] then max:=(q2[j]-q1[j]+1)*a[j]; end; end; procedure write_data; begin writeln(max); end; begin { assign(input,'building.in'); reset(input); assign(output,'building.out'); rewrite(output);} read_data; write_data; { close(input);close(output);} end.
Country. Смішно стає, коли дивишся деякі розвязки учасників. Все набагато легше:)
var a:array[1..50000] of byte; b,c:array[1..3] of word; i,n,ans:word; procedure read_data; begin read(n); for i:=1 to n do begin read(a[i]); inc(b[a[i]]); end; end; procedure algor; function max(q,w:word):word; begin if q>w then max:=q else max:=w; end; begin for i:=1 to n do case a[i] of 1:if i>b[1] then inc(c[a[i]]); 3:if (i<=b[1]) or (i>b[1]+b[3]) then inc(c[a[i]]); 2:if i<=b[1]+b[3] then inc(c[a[i]]); end; ans:=max(max(c[1],c[2]),c[3]); end; procedure write_data; begin writeln(ans); end; begin { assign(input,'country.in'); reset(input); assign(output,'country.out'); rewrite(output);} read_data; algor; write_data; { close(input);close(output);} end.
Dsp.
const con=200; var a:array[1..con,1..con] of longint; tem,k,n,m,q,w,i,j:longint; procedure read_data; begin read(n,m,q,w); end; procedure algor; function min(q,w:longint):longint; begin if q<w then min:=q else min:=w; end; begin {suppose that first side >= then second} if n<m then begin tem:=n;n:=m;m:=tem; end; if q<w then begin tem:=q;q:=w;w:=tem; end; a[q][w]:=1;a[w][q]:=1; for i:=q to n do for j:=1 to min(i,m) do begin for k:=1 to i div 2 do if (a[i][j]<a[k][j]+a[i-k][j]) then a[i][j]:=a[k][j]+a[i-k][j]; for k:=1 to j div 2 do if (a[i][j]<a[i][k]+a[i][j-k]) then a[i][j]:=a[i][k]+a[i][j-k]; a[j][i]:=a[i][j]; end; end; procedure write_data; begin writeln(a[n][m]); end; begin { assign(input,'dsp.in'); reset(input); assign(output,'dsp.out'); rewrite(output);} read_data; algor; write_data; {close(input);close(output);} end.
Primenum. Мабуть найтупіший мій розвязок на цій олімпіаді:)
var now,kil,g,x,y,z,q,w,e,a,b,c,n:longint; d:array[1..10000] of longint; res:extended; procedure read_data; begin read(a,b,c,n); end; procedure algor; procedure sort(l,r: longint); var i,j: longint; begin i:=l; j:=r; x:=d[(l+r) div 2]; repeat while d[i]<x do inc(i); while x<d[j] do dec(j); if not(i>j) then begin y:=d[i]; d[i]:=d[j]; d[j]:=y; inc(i); j:=j-1; end; until i>j; if l<j then sort(l,j); if i<r then sort(i,r); end; function pow(l:extended;r:longint):extended; begin res:=1; for g:=1 to r do res:=res*l; pow:=res; end; begin now:=1; for q:=0 to 40 do begin if now*(a+0.0)>maxlongint then break; now:=now*a; end; now:=1; for w:=0 to 40 do begin if now*(b+0.0)>maxlongint then break; now:=now*b; end; now:=1; for e:=0 to 40 do begin if now*(c+0.0)>maxlongint then break; now:=now*c; end; for x:=0 to q do for y:=0 to w do if pow(a,x)*pow(b,y)<maxlongint+1.0 then for z:=0 to e do if pow(a,x)*pow(b,y)*pow(c,z)<maxlongint+1.0 then begin inc(kil); d[kil]:=trunc(pow(a,x)*pow(b,y)*pow(c,z)); end; sort(1,kil); end; procedure write_data; begin writeln(d[n]); end; begin { assign(input,'primenum.in'); reset(input); assign(output,'primenum.out'); rewrite(output);} read_data; algor; write_data; { close(input);close(output);} end.
взагалі сішникам була шара:
#include <set> #include <iostream> using namespace std; const long MAX=(1<<30)+((1<<30)-1); set<long> mas; int main() { mas.insert(1); long a,b,c,n; cin>>a>>b>>c>>n; for(int i=1;i<n;i++) { long num=*mas.begin(); mas.erase(mas.begin()); if (num*(a+.0)<=MAX) mas.insert((long) (num*a)); if (num*(b+.0)<=MAX) mas.insert((long) (num*b)); if (num*(c+.0)<=MAX) mas.insert((long) (num*c)); } cout<<*mas.begin(); return 0; }
І накінець Wood
const con=500; _eps=1e-8; type typ=extended; rec=record x,y:typ; end; var a:array[0..con-1] of rec; count,n,i,j:longint; maxh,b1,b2,mid,S,x,r:typ; procedure read_data; begin read(n); for i:=0 to n-1 do begin read(a[i].x,a[i].y); if a[i].y>maxh then maxh:=a[i].y; end; read(r); end; procedure algor; function eq(q,w:typ):boolean; begin eq:=abs(q-w)<_eps; end; function more(q,w:typ):boolean; begin more:=q-w>_eps; end; function lesseq(q,w:typ):boolean; begin lesseq:=q-w<_eps; end; function min(q,w:typ):typ; begin if q<w then min:=q else min:=w; end; function max(q,w:typ):typ; begin if q>w then max:=q else max:=w; end; function dist(x1,y1,x2,y2:typ):typ; begin dist:=sqrt(sqr(x1-x2)+sqr(y1-y2)); end; function calc(y:typ):typ; var res:typ; begin res:=0;count:=0; for i:=0 to n-1 do begin j:=(i+1) mod n; if more(y,min(a[i].y,a[j].y)) and lesseq(y,max(a[i].y,a[j].y)) then begin x:=(y-a[i].y)*(a[j].x-a[i].x)/(a[j].y-a[i].y)+a[i].x; if count=0 then res:=res+dist(a[i].x,a[i].y,x,y) else res:=res+dist(x,y,a[j].x,a[j].y); inc(count); end else if count<>1 then res:=res+dist(a[i].x,a[i].y,a[j].x,a[j].y); end; calc:=res; end; begin for i:=0 to n-1 do S:=S+dist(a[i].x,a[i].y,a[(i+1) mod n].x,a[(i+1) mod n].y); b1:=0; b2:=maxh; while (b2-b1>1e-6) do begin mid:=(b1+b2)/2; if calc(mid)>S*r then b2:=mid else b1:=mid; end; end; procedure write_data; begin writeln(mid:0:2); end; begin { assign(input,'wood.in'); reset(input); assign(output,'wood.out'); rewrite(output);} read_data; algor; write_data; { close(input);close(output);} end.
Поза форумом
А мне очень жалко что проходит ДСП за (m+n)*m*n
Поза форумом
Ivan написав:
А мне очень жалко что проходит ДСП за (m+n)*m*n
За сколько у тебя проходит?
Поза форумом
Офигеть... В первом туре жюри все твердило: "ваше решение не проходит, так как работате на 0.001 с больше, чем надо".
А здесь тупейшие решения получили по полному баллу, причем при их составлении никто даже особо не задумывался, правильное и оптимальное ли это решение. Я хорошо помню, как то же жюри говорило, что хотелось бы, чтобы участники хоть немного думали и не посылали халявные программы в надежде, что они прокатят.
В итоге: у нас пятеро человек набрали полный балл, но тем не менее в списке они стоят под разными номерами, а не под 1... Это как понимать?!
Остается надеятся только на одно: что в онлайн-туре жюри будет более внимательно к получаемым решениям, раз уж задалось такой целью в первом... Хотя, так можно думать только потому что надежда умирает последней... =)
Відредаговано Raziel Redstone (2005-12-21 19:20:59)
Поза форумом
40 баллов :-)
я лажу не гоню :-)
Поза форумом
Ivan! Ты все время говоришь, что знаешь решение DSP за меньшее чем O(m*n*(m+n)) время. Так выложи, поясни и докажи!
Поза форумом
netoi.ho.com.ua я же, вроде тебе об этом уже говорил
Поза форумом
reiten написав:
Ivan! Ты все время говоришь, что знаешь решение DSP за меньшее чем O(m*n*(m+n)) время. Так выложи, поясни и докажи!
Мое решение: первый разрез не любой, а всегда отрезаем горизонтальные или вертикальные полосы ширины A или B.
#include <iostream> using namespace std; void Order(long &a, long &b, bool a_smaller_b = true) { if (a > b == a_smaller_b) {long t = a; a = b; b = t;}} long w, h, a, b; long ans[256][256]; long dvd_a[256], dvd_b[256]; int main() { long i, j; cin >> w >> h >> a >> b; Order(a, b); for (i = 0; i < 256; ++i) { dvd_a[i] = i / a; dvd_b[i] = i / b; } memset(ans, 0, sizeof(ans)); for (i = 1; i <= h; ++i) for (j = 1; j <= w; ++j) { ans[i][j] = max(ans[i][j - 1], ans[i - 1][j]); if (j >= a) { ans[i][j] = max(ans[i][j], ans[i][j - a] + dvd_b[i]); if (j >= b) ans[i][j] = max(ans[i][j], ans[i][j - b] + dvd_a[i]); } if (i >= a) { ans[i][j] = max(ans[i][j], ans[i - a][j] + dvd_b[j]); if (i >= b) ans[i][j] = max(ans[i][j], ans[i - b][j] + dvd_a[j]); } } cout << ans[h][w] << endl; return 0; }
Я доказал так:
1. Если M = A то ответ - N div B. Аналогично - случаи когда M = B, N = A или N = B.
В принципе это очевидно, но я повозился с точным доказательством. Могу написать.
2. По индукции: для любых M, N, A и В правильное решение всегда можно начать с отрезания полосы ширины А или полосы ширины B, либо горизонтальной, либо вертикальной (т.е. один из 4 вариантов всегда окажется правильным). Доказательство нетривиально, но и не слишком сложно. Расписывать полностью - сильно громоздко выйдет, но я попробую .
Предположим, что в правильном решении первый разрез НЕ отрезает полосу ширины A или B, и такого результата нельзя получить отрезая A или B. Будем считать что он, этот первый разрез - вертикальный, т.е. длины N.
Итак, имеем два прямоугольника: UxN и VxN, U + V = M. Для каждого из них выполняется доказуемое утверждение, т.е. для них правильный первый разрез отрезает полосу ширины либо А либо В. Если хоть один из этих разрезов - вертикальный, то его можно выполнять первым (если он не у края - горизонтальная симметрия действий в его прямоугольнике). Остался один вариант - оба горизонтальные. Тогда если оба - А или оба - В, то их можно выполнить одним, первым разрезом (опять, если один сверху, а другой снизу, вертикальная симметрия в любом из 2х прямоугольников). Значит остался (самый сложный) вариант - один из них - А, другой - В, оба горизонтальные.
Вот здесь я и остановлюсь. Дальше идея в том, что мы последовательно (вглубь, отрезая полосы) изучаем структуру каждого из двух прямоугольников, и обязательно приходим к тому, что всегда найдется либо вертикальный, либо общий горизонтальный разрез. Для этого понадобится утверждение №1, т.к. оно дает нам возможность говорить, что если, скажем, в левом прямоугольнике сделан сверху горизонтальный разрез ширины А, то эту (верхнюю) полосу можно смело (без ухудшения решения) считать разрезанной на вертикальные полосы ширины В, и не иначе. Именно из этой однозначной структуры у нас получится совмещать разрезы в один сквозной.
Очень может быть что доказательство излишне громоздкое, но я довел его до конца полностью, без всяких "интуитивно понятно что" и т.п., так что если кому сильно захочется проверить - давайте.
Відредаговано Rybak (2005-12-21 22:35:49)
Поза форумом
Я лично получил 21 балл за тупое решение 2-ой задачи:
Просто писал результат (x*y)div(a*b)
Поза форумом
Думаешь 21 это круто?
Баллы вполне соответствуют "умности" решения.
Поза форумом
Rybak написав:
без всяких "интуитивно понятно что" и т.п.
Ну если ты это про меня :-) то суть в чем: зачем доказывать если можно просто напросто проверить?
Поза форумом
Ivan написав:
Rybak написав:
без всяких "интуитивно понятно что" и т.п.
Ну если ты это про меня :-) то суть в чем: зачем доказывать если можно просто напросто проверить?
Нет, совсем не про тебя. Я просто имел ввиду что в моем тексте я опускаю куски доказательства, но могу привести его полностью, без "интуитивно понятно" и "можно доказать что".
Твое решение прикольное, и его ценность меньше не становится оттого что оно доказано проверкой. Теорему о четырех красках доказали с помощью перебора, который длился черти сколько дней (ясное дело, самым сложным было обобщить результаты перебора на случай произвольной карты, но все-таки!)
Поза форумом