На форумі обговорюються лише питання, пов'язані з олімпіадою
Ви не зайшли.
Итак у меня:
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 написав:
без всяких "интуитивно понятно что" и т.п.
Ну если ты это про меня :-) то суть в чем: зачем доказывать если можно просто напросто проверить?
Нет, совсем не про тебя. Я просто имел ввиду что в моем тексте я опускаю куски доказательства, но могу привести его полностью, без "интуитивно понятно" и "можно доказать что".
Твое решение прикольное, и его ценность меньше не становится оттого что оно доказано проверкой. Теорему о четырех красках доказали с помощью перебора, который длился черти сколько дней (ясное дело, самым сложным было обобщить результаты перебора на случай произвольной карты, но все-таки!)
Поза форумом