infoarena

infoarena - concursuri, probleme, evaluator, articole => Arhiva de probleme => Subiect creat de: Paul-Dan Baltescu din Decembrie 05, 2010, 13:50:24



Titlul: 1087 Doi
Scris de: Paul-Dan Baltescu din Decembrie 05, 2010, 13:50:24
Aici puteţi discuta despre problema Doi (http://infoarena.ro/problema/doi).


Titlul: Răspuns: 1087 Doi
Scris de: Macarescu Sebastian din Decembrie 05, 2010, 20:09:54
Imi da si mie cineva o idee? Nu gasesc deloc solutia desi parea cea mai usoara.


Titlul: Răspuns: 1087 Doi
Scris de: Simoiu Robert din Decembrie 05, 2010, 20:31:14
Poti sa faci o abordare de tip greedy : daca numarul e par, atunci il imparti la 2, daca e impar faci asa : te duci pe doua cazuri .... unul incrementand, unul decrementand. Pentru fiecare caz, mergi pana ajungi la un numar impar. Vezi in care caz ajungi mai departe, si iei acel numar, incrementand solutia.
Exemplu avem numarul 15. E impar, deci vedem cazurile :
1. Daca il incrementam, avem 16, e par deci il impartim la 2, 16 / 2 = 8, 8 par => 8 / 2 = 4, 4 = par => 4 / 2 = 2, 2 par => 2 / 2 = 1.
2. Daca il decrementam, avem 14, e par deci il impartim la 2, 14 / 2 = 7.
Se vede ca in primul caz am facut 4 pasi, si in al doilea am facut doar 1 pas. Deci avem pana acum sol = 5. Avem 1, iarasi 2 cazuri.
1. Daca il incrementam, avem 2, e par deci il impartim la 2, avem 2 / 2 = 1.
2. Daca il decrementam, avem 0 => am ajuns la final.
Solutia finala o sa fie 5 + 1 = 6 .


Titlul: Răspuns: 1087 Doi
Scris de: Macarescu Sebastian din Decembrie 05, 2010, 21:13:07
M-am gandit si la solutia asta dar nu cred ca intra in timp pentru un numar de 500 cifre.


Titlul: Răspuns: 1087 Doi
Scris de: Simoiu Robert din Decembrie 05, 2010, 21:31:48
Ce ziceai ? http://infoarena.ro/job_detail/507378


Titlul: Răspuns: 1087 Doi
Scris de: Alexandru-Iancu Caragicu din Decembrie 05, 2010, 21:40:25
fie x = 2^a    cea mai mare putere a lui 2, mai mica decat nr
y = 2^b       cea mai mica putere a lui 2, mai mare decat nr
Ranspunsul nu e

daca x<y
     a + n-x
altfel
     b + y-n             ?


Titlul: Răspuns: 1087 Doi
Scris de: Simoiu Robert din Decembrie 05, 2010, 21:49:20
Dar nu tot timpul, x < y in cazul tau ?


Titlul: Răspuns: 1087 Doi
Scris de: Farcas Ionut din Decembrie 06, 2010, 17:25:35
nu afisati pls un fisier de intrare sau un exemplu ca mie acasa imi da rezultat corect pt orice numar dar am scos 0 pct si nu stiu dc  ](*,)


Titlul: Răspuns: 1087 Doi
Scris de: Lepadat Mihai-Alexandru din Decembrie 06, 2010, 19:57:47
IN:
Cod:
7
1000
65
47
651
251
984318494894851312348949845645645645184948948513184948948513
4849448646843129849848445645645645445645645645184984944868494486

OUT:
Cod:
13
8
8
14
11
265
286

Succes!  :ok:


Titlul: Răspuns: 1087 Doi
Scris de: Pripoae Teodor Anton din Decembrie 06, 2010, 20:58:27
Deci solutia ar fi in felul urmator:

Scri numarul in baza 2. Notezi cu x lungimea grupei de 1 din coada numarului. Daca x = 1 atunci e clar ca o sa scazi 1 din numar, altfel vei aduna 1, micsorand numarul de biti de 1. Daca e 0, imparti la 2.

Exemplu

A = 110001000111
B = 101010101010

Pt A vei aduna 1 la ultima grupa, transformandu-se in 110001001000, apoi imparti de 3 ori la 2, apoi scazi 1, etc. Pt B vei scadea de fiecare data 1, pt ca nu sunt grupe de 1 de lungime mai mare de 1.

Sper ca ai inteles ce-am zis, n-am explicat prea bine.


Titlul: Răspuns: 1087 Doi
Scris de: Vlad Tarniceru din Decembrie 06, 2010, 21:17:13
dar de ce este necesar sa scri numarul in baza 2, nu merge si fara, sau e pentru optimizare?


Titlul: Răspuns: 1087 Doi
Scris de: Pripoae Teodor Anton din Decembrie 06, 2010, 21:50:13
Eu asa am facut. Nu prea vad cum ai face altfel sa vezi cati de 1 ai consecutiv. E posibil sa fie si alte solutii.


Titlul: Răspuns: 1087 Doi
Scris de: Lepadat Mihai-Alexandru din Decembrie 06, 2010, 21:56:11
Merge si sa-i aduni numarului 1, respectiv sa-i scazi 1, iar apoi sa verifici care dintre cele doua noi numere se imparte de mai multe ori la 2(il imparti efectiv). Intra in timp destul aproape de limita aceasta abordare, insa iei 100.


Titlul: Răspuns: 1087 Doi
Scris de: Farcas Ionut din Decembrie 06, 2010, 22:01:05
ms pt test uitasem sa pun o simpla conditie si am pierdut 100 de pct la runda 1 :((.. si eu am facut cu baza 2 ... numa ca eu aducem numarul  la forma 1000...0 care era o putere de 2 si atuncea rasounsu era nr de cifre  din 100...0 plus nr de operatii efectuate pt a ajunge akl : ex 1001101 se face 1001100 apoi 1010000 si in final 1000000 deci raspuns 10 :D si mio iesit 100 pct.:D


Titlul: Răspuns: 1087 Doi
Scris de: cristescu liviu din Decembrie 07, 2010, 07:25:29
da, toni, am descoperit si eu solutia asta, pe aproape cum ai explicat-o tu, doar ca nr de operatii este trecerea numarului in baza 2  + cate operatii efectuezi ca sa ajungi la o putere de-a lui 2 apropiata, stiu ca suna ilogic, un ex.63=11111
astaa inseamna 5 cifre, adik s=5;
aduni un 1 si rezulta 1000000s-a marit numarul de cifre + operatia s=7 si gata,
exceptie fac numerele care incep cu 110 in baza 2 pt ca acolo e caz special si numarul 3 mai este caz special


Titlul: Răspuns: 1087 Doi
Scris de: Simoiu Robert din Decembrie 07, 2010, 15:16:01
Merge si sa-i aduni numarului 1, respectiv sa-i scazi 1, iar apoi sa verifici care dintre cele doua noi numere se imparte de mai multe ori la 2(il imparti efectiv). Intra in timp destul aproape de limita aceasta abordare, insa iei 100.
Uite solutia ta cu timpi zic eu foarte buni http://infoarena.ro/job_detail/507378 .


Titlul: Răspuns: 1087 Doi
Scris de: Pripoae Teodor Anton din Decembrie 07, 2010, 16:36:12
http://infoarena.ro/job_detail/507469


Titlul: Răspuns: 1087 Doi
Scris de: intermediar din Decembrie 09, 2010, 13:12:53
Nu inteleg de ce nu merge sursa.Va rog daca puteti sa-mi da-ti o indicatie .... Multumesc


Titlul: Răspuns: 1087 Doi
Scris de: Simoiu Robert din Decembrie 09, 2010, 15:37:16
Da-ne tu indicatii cum ai facut si poate te putem ajuta ....


Titlul: Răspuns: 1087 Doi
Scris de: Dumitraiche Marius-Alexandru din Decembrie 09, 2010, 21:25:44
ce am gresit aici:( nu inteleg. o mica explicatie va rog ?
sunt incepator pe aici.
plz

Cod:
http://#include<fstream>
using namespace std;
#define InPut "doi.in"
#define OutPut "doi.out"
int c,t,i,nr,a;
int main()
{
ifstream fin ( InPut );
ofstream fout ( OutPut );
fin>>t;
for(i=1;i<=t;i++)
{
fin>>a;
   nr=0;
   while(a!=0)
   {
           if(a%2==0)
    { c=a/2;
      nr++;
}
  else
{ c=a-1;
      nr++;
}
a=c;
   }
fout<<nr<<"\n";
}
return 0;
}

Editat de moderator : Foloseste tag'urile [ code ] si [ /code] cand postezi cod


Titlul: Răspuns: 1087 Doi
Scris de: Vlad Tarniceru din Decembrie 09, 2010, 21:49:50
cred ca erorile tale ar putea fi urmatoarele:
1.ar fi http-ul ala de la inceput dar cred ca a aparut de la site
2.ai grija ca implementarea trebuie pe nr mari
3.nici solutia nu e buna, tu poti si sa aduni nu numai sa scazi, citeste solutia lui robert simoiu din acest topic si incearca sa o faci pe numere mari pentru 100 de puncte (operatiile pe numere mari le gasesti in articolul cu smenuri de programare)

bafta  :peacefingers:


Titlul: Răspuns: 1087 Doi
Scris de: Dumitraiche Marius-Alexandru din Decembrie 10, 2010, 17:10:40
multumesc!!!  o sa incerc


Titlul: Răspuns: 1087 Doi
Scris de: Vasilut Lucian din Ianuarie 30, 2011, 16:36:14
am o problema .....la numerele impare nr de operatii mi-l afiseaza ca find chiar numarul......o sugestie ceva... #-o


Titlul: Răspuns: 1087 Doi
Scris de: George Marcus din Ianuarie 30, 2011, 20:58:04
De unde sa stie lumea ca ce gresesti tu? Posteaza ideea sau o parte din sursa de la programul tau... dar a fost deja explicata destul de detaliat ideea mai sus.


Titlul: Răspuns: 1087 Doi
Scris de: Ciprian Tomoiaga din Februarie 15, 2011, 20:29:55
oare de ce ar vrea cineva sa incrementeze numarul? asta nu e clar ca te va duce catre un numar mai mare de operatii? aveti cumva vreun contra-exemplu?


Titlul: Răspuns: 1087 Doi
Scris de: Eugenie Daniel Posdarascu din Februarie 15, 2011, 20:41:29
Uite un exemplu. Pentru n=15 cel mai bine e sa incrementezi cu 1 sa obtii 16 ca pe orma sa poti impartii la 2 de 4 ori. Daca decrementezi cu 1 si obtii 14 o sa observi ca ai mai multe operatii.


Titlul: Răspuns: 1087 Doi
Scris de: Simoiu Robert din Februarie 15, 2011, 21:10:32
De accea se foloseste o strategie greedy, vazand la fiecare pas alegerea optima.


Titlul: Răspuns: 1087 Doi
Scris de: FMI Ekart Dragos-Ioan din Februarie 24, 2011, 16:00:28

algoritmul dat la raspuns are o greseala pentru cazul in care este Multiplu de 3 inmultit cu o putere a lui 2


Titlul: Răspuns: 1087 Doi
Scris de: Simoiu Robert din Februarie 24, 2011, 16:18:36
Ne poti da un exemplu si cat da programul acela ?


Titlul: Răspuns: 1087 Doi
Scris de: FMI Ekart Dragos-Ioan din Februarie 24, 2011, 16:19:48
Cod:
01.#include<fstream> 
02.using namespace std;
03.long long int nr;
04.ifstream in ("doi.in");
05.ofstream out ("doi.out");
06.int main (){
07.long long int n,i,j;
08.in>>n;
09.for(i=0;i<n;i++){
10.   
nr=0;
11.in>>j;
12.while(j>0){
13.if(j%2==0){
14.j=j/2;
15.nr++;
16.continue;
17.}
18.if(((j-1)/2)%2==0){
19.if((j-1)==0){
20.nr++;
21.break;
22.}
23.else{
24.nr+=2;
25.j=(j-1)/2;
26.}
27.continue;
28.}
29.if((j-1)/2==1){
30.   
nr+=3;
31.   
break;
32.}
33.if(((j+1)/2)%2==0){
34.   
j=(j+1)/2;
35.   
nr+=2;
36.}
37.}
38.out<<nr<<"\n";
39.}
40.in.close();
41.out.close();
42.return 0;
43.}.
nu inteleg de ce iau numai 40 de puncte unde gresesc


Titlul: Răspuns: 1087 Doi
Scris de: FMI Ekart Dragos-Ioan din Februarie 24, 2011, 16:22:52
iti pot de un exemplu daca folosesc strict algoritm dat la solutie cand vrei sa vezi pentru 3 iti va da 4 deorece 3=2*1+1 unde k =1 aplicand rezolvarea de la problema se duce pe ramura a doua deoarece nu este k par


Titlul: Răspuns: 1087 Doi
Scris de: Simoiu Robert din Februarie 24, 2011, 16:33:43
Pentru 3, folosind STRICT algoritmul acela, o sa ai rezultatul 3, pentru ca din 3 + 1, sau 3 - 1, alegi 3 - 1, pentru ca mergi mai mult. Adica 3 - 1 = 2, cum 2 par => 2 / 2 = 1. Si acum scazi o unitate si gata. Daca ai fi la 3 + 1, ai avea 4 / 2 = 2, 2 / 2 = 1, iar apoi 0, ceea ce o sa iti dea rezultatul 4. Cum 3 < 4, alegi rezultatul 3.


Titlul: Răspuns: 1087 Doi
Scris de: Alexandru Meterez din Aprilie 16, 2011, 11:08:42
Cod:
#include <iostream>
#include <math.h>
#include <cstdio>
using namespace std;
int main(){
    freopen("doi.in","r",stdin);
    freopen("doi.out","w",stdout);

long long n,a[1000],i,c=0;
cin>>n;
for(i=1;i<=n;i++)
    cin>>a[i];

for(i=1;i<=n;i++)
{
    c=0;
    while(a[i]!=0)
 {//calculam pt nr par
    if(a[i]%2==0)
        {a[i]=a[i]/2; c++;}

    //partea a doua pt nr impar
    else if(a[i]%2==1)
        {a[i]--; c++;}
}
    cout<<c<<'\n';
}


return 0;
}


Da-ti si voi un ochi va rog !  ](*,) ](*,)


Titlul: Răspuns: 1087 Doi
Scris de: George Marcus din Aprilie 16, 2011, 12:28:24
1) Trebuie sa iei in calcul si posibilitatea de a aduna 1, nu doar de a scadea.
2) Trebuie sa lucrezi cu numere mari din cauza restrictiilor problemei.

P.S.: Inainte sa intrebi ceva, o idee buna e sa verifici daca nu cumva au avut si altii aceeasi problema.


Titlul: Răspuns: 1087 Doi
Scris de: Valentin Harsan din Mai 22, 2011, 08:57:37
nu inteleg ce gresesc ](*,)
poate sa se uite cineva pe sursa mea, va roog

Cod:

#include<stdio.h>
#include<string.h>

int t,nrr[505],nr[505],a1,nu,a2,nr2[505];
char a[510];

void imp(int v[]) {
int i,t=0;
for(i=v[0];i>0;--i) {
t=t*10+v[i];
v[i]=t/2; t%=2;
}
for(;v[v[0]]==0;--v[0]);
}
int smax(int a1,int a2) {
if(a1>a2) return a1;
return a2;
}
void add(int a) {
int i,t=0; nrr[1]+=a;
for(i=1;t || i<=nrr[0];++i,t/=10) {
t+=nrr[i];
nrr[i]=t%10;
}
nrr[0]=smax(i-1,nrr[0]);
}
void add2(int a) {
int i; nr2[1]-=a;
for(i=1;i<=nr2[0];++i) {
if(nr2[i]<0) {
nr2[i]+=10;
nr2[i+1]--;
}
}
for(;!nr2[nr2[0]] && nr2[0]!=0;--nr2[0]);
}

bool cmp() {
int j;
if(nrr[0]!=nr2[0]) return 0;
for(j=nrr[0];j>0;--j)
if(nrr[j]!=nr2[j]) return 0;
return 1;
}

int main() {
int i,w;
freopen("doi.in","r",stdin);
freopen("doi.out","w",stdout);
scanf("%d",&t);
for(w=1;w<=t;++w) {
scanf("%s",&a); a1=strlen(a);
nu=0; nr[0]=0;
for(i=a1-1;i>=0;--i)
nr[++nr[0]]=a[i]-'0';
while(nr[0]!=0) {
++nu;
if((nr[1]&1)==0)
imp(nr);
else {
a1=0;
for(i=0;i<=nr[0];++i)
nrr[i]=nr[i];
add(1);
while((nrr[1]&1)==0) {
++a1;
imp(nrr);
}
a2=0;
for(i=0;i<=nr[0];++i)
nr2[i]=nr[i];
add2(1);
if(!nr2[0])
break;
while((nr2[1]&1)==0) {
++a2;
imp(nr2);
}
if(a2>a1) {
if(cmp())
nu+=a1;
else
nu+=a2;
for(i=0;i<=nr2[0];++i)
nr[i]=nr2[i];
}
else {
if(cmp())
nu+=a2;
else
nu+=a1;
for(i=0;i<=nrr[0];++i)
nr[i]=nrr[i];
}
}
}
printf("%d\n",nu);
}
return 0;
}


Titlul: Răspuns: 1087 Doi
Scris de: UAIC.VlasCatalin din Octombrie 03, 2013, 18:57:32
Va rog ajutati-ma cu testele 2 si 8 ca nu ma prind, am facut solutia in care incersc sa merg pe doua cazuri cind adun sau scad 1.  ](*,)


Titlul: Răspuns: 1087 Doi
Scris de: George Marcus din Octombrie 03, 2013, 20:51:55
Nu stiu daca are legatura cu testele, dar ar trebui sa bagi in seama warningurile compilatorului, in special asta:
Cod:
warning: control reaches end of non-void function

pentru cazul cand numerele sunt egale.


Titlul: Răspuns: 1087 Doi
Scris de: Eric Spataru din Aprilie 13, 2014, 19:39:37
Apucandu-te de problema abia dupa ce realizezi ca se fac 3 operatii cu numere mari... ](*,)