From: | "Mihai Patrascu" <mihai_p@pcnet.ro> | Block address | Add to Address Book |
To: | "probleme" <probleme@ldc.ro> |
Subject: | sunt destept |
Date: | Wed, 21 Feb 2001 22:03:12 +0200 |
|
|
Ma rog, cine ma cunoaste stie ca ce scrie in subject e in general
valabil,
dar stati sa va zic cum am mai ajuns la concluzia asta de data asta...
In culegerea lui Catalin Francu (Psihologia...) e data o problema
exemplu la
structuri mari de date: Intr-un fisier de intrare ai primele N numere
intregi pozitive date intr-o ordine oarecare din care s-a eliminat fix
unul.
Trebuie sa spui care numar lipseste.
Metoda superdesteapta gasita de Cata e sa calculezi N(N+1)/2 cu numere
mari,
sa aduni numerele din fisier si sa scazi din suma asteptata suma
obtinuta.
Astfel iti da fix numarul lipsa. Zice el metoda ia ceva timp de
implementare.
Metoda rapida gasita de el e sa tii un vector de biti si sa marchezi
numerele primite. Dup-aia scanezi vectorul dupa un zero.
Sa presupunem ca sunt rau si propun subiecte la un concurs. Dau un unit
care
sa returneze urmatorul numar, in loc sa citesti fisier de intrare
(practic
trebuie sa generezi o permutare a numerelor de la 1 la N, poti face
ceva in
inelul claselor de resturi, nu e greu). Pun N maxim 100 mil. (deci
metoda
doi iese din discutie) si timpul cateva sec (pe Pentium III @750 nici
nu se
pune problema sa intre in timp metoda unu, oricum ai implementa-o).
Inainte de a trece mai departe va rog sa va luati cateva minute de
gandire
(si 1/2 - 1 ora daca vreti). Sunt foarte curios cati ar face problema
la un
concurs...
x
x
x
x
x
x
x
x
x
x
x
x
Daca ati trecut de x-uri, inseamna ca v-ati gandit, eventual ati
impelementat ceva. Daca puteti, dati un mail "eu m-am prins" sau "eu
nu".
Mai avem si ceva activitate pe lista cu ocazia asta :) si fac si eu o
statistica.
Deci, cum se face pana la urma problema??? Aplici THE SUPERMETODA
Patrascu.
Codul e urmatorul:
int main()
{
unsigned long n, s;
n = gimme_n();
s = (n & 1) ? n * ((n + 1) >> 1) : (n >> 1) * (n + 1);
for(; n--; s -= gimme_next()) ;
printf("%ld\n", s);
return(0);
}
Intelegeti??? Practic N(N+1)/2 nu trebuie sa-l calculezi cu numere
mari.
Calculezi decat cei mai putin semnificativi 32 de biti (linia care
incepe cu
"s=" chiar asta calculeaza). Dup-aia scazi in aritmetica pe 32 de biti
numerele pe care le primesti (ignori imprumuturile la scadere). Daca
modulul
extern merge bine, rezultatul e garantat sa dea un numar intre 1 si N.
Plus,
daca am fi calculat cu numere mari, rezultatul final e garantat sa fie
zero
de la bitul 32 in sus. Deci pe parcursul rezolvarii nu e nevoie
niciodata
decat de cei mai putini semnificativi 32 de biti. Deci nu trebuie
numere
mari, de la 32 de biti in sus se poate ignora pur si simplu (adica
toate
calculele se pot face in inelul mod 2**32).
Ce ziceti???
BTW, Cata, stii ca DEKnuth da cate un CEC de $2.56 daca gasesti asa
ceva in
Arta Programarii. Nu imi trebuie $2.56, dar a postcard cu autograf ar
fi
apreciata.
:-). Daca m-ai luat in serios, adresa mea s-mail este:
Mihai Patrascu, Str. Maresal Alexandru Averescu, bloc N9, apt. 4
1100 Craiova, ROMANIA
Presupunand prin absurd ca imi public vreodata o carte si gasesti asa
ceva
in cartea mea, iti trimit si eu tie una :-)
mihai_p
Privacy Policy-
Terms of Service
-
Guidelines
Copyright © 1994-2001
Yahoo! Inc. All rights reserved.