10 / 19
Feb 2016

Mam taki kod i nie wiem jak rozwiązać problem ze zmiennymi.

#include <stdio.h>
int main()
{
    unsigned long a1, a2, b1, b2, c1, c2;
    //jaki typ zmiennych?// a, b, c;
    int t;
    scanf("%d", &t);
        while( t-- )
        {
            scanf("%ld/%ld %ld/%ld %ld/%ld", &a1, &a2, &b1, &b2, &c1, &c2);
            //jakie przypisania do zminnych a, b, c//
            if( a+b>c && a+c>b && b+c>a ) printf("TAK\n");
            else printf("NIE\n");
        }
    return 0;        
}
  • created

    Jul '08
  • last reply

    Oct '21
  • 18

    replies

  • 2.1k

    views

  • 8

    users

  • 2

    likes

  • 3

    links

1 year later

Mam identyczny problem dwa testy przechodzi w 0,1;0,2sek a pozostałe to "przekroczenie limitu czasu" jakies 3sek czy ktos z poprawną odp mógłby cos podpowiedzieć?

3 months later

Odgrzebię temat trochę, no ale...

Nie mam pojęcia, co dalej z tym zadaniem zrobić, już nie korzystam z double, obliczam nww, dzielę liczby w odpowiedniej kolejności, żeby nie przekroczyć zakresu. Zalicza mi 3 testy w łącznym czasie 0.01, nie zalicza mi pierwszego, który jak mniemam jest najprostszy. Prosiłbym o jakąś radę.

Pozdrawiam.

21 days later

Hmm.
Sam mam 3/4pkt, ale udało mi się taki trick zrobić: zamieniłem long long inta na double i po tym zabiegu zerowy test zaliczony, ale za to drugi (w kolejności trzeci) test WA.

PS long double daje to samo, co double, a unsigned long long int to samo co long long int.

Więc dołączam się do prośby o podpowiedź. smile

Czy nikt z was nie zauwazyl, ze wyniki nie mieszcza sie w standardowych typach danych ?

Miałem właśnie wątpliwości, co do tego, ale jak dostałem AC z long longiem dla 1-go, 2-go i 3-go testu oraz AC z double dla 0-go, 1-go i 3-go testu (więc miałem jakby wszystkie zaliczone, ale osobno), to stwierdziłem, że błąd leży gdzie indziej. smile
Bo trochę dziwne, że zalicza wszystkie testy oprócz jednego a pamięci zajmuje tyle samo, więc testy są podobne (chyba).

1 month later

Czemu wyniki nie wieszczą się w standardowych typach danych?
Doczytałem teraz w treści zadania, że:

Może jednak ktoś zrobił to na standardowych typach, a nie na arytmetyce dużych liczb?

6 years later

Właśnie skasowałem komentarz Anonima pod tym zadaniem. Oto ten komentarz:

2016-02-24 14:48:01 anonimowy
Zadanie jest według mnie bardzo źle sformułowane, za co jednak nie
sposób winić autora - dobre jego sformułowanie uczyni go zadaniem łatwym
(banalnym?). Wyniki 0/4 i 1/4 są zrozumiałe i oznaczają, że robimy coś
bardzo źle. Wynik 2/4 oznacza, że zadanie już umie się rozwiązać i dalej
trzeba kombinować tak, aż uzyska się to, co autor miał na myśli
twierdząc, że: "do rozwiązania wystarczy 64-bitowy zakres zmiennych".
Wynik 3/4 jest jednak dość męczący: w zależności od tego, który test nie
jest zaliczany, przyczyna problemu jest inna i trudno ją wskazać.
Jeżeli ktoś nie zrozumie intencji autora (a trudno jest je pojąć mając
tylko treść zadania) to będzie tworzył cuda typu BigInt i nie będzie
miał większych szans na poprawę swojego wyniku. Wówczas może, tak jak
ja, zacząć szukać porad w Internecie. Może też, tak jak ja, trafić na
gotowca i... załamać się, że to zadanie jest tak banalne! Sporo osób nie
chce jednak na gotowca trafić a przez to rozwiązanie zadania staje się
niemałym wyzwaniem - wystarczy dodać do siebie dwa ułamki by przekonać
się, że 64-bitowa zmienna jest za mała (WA), o ile nie dokona się po
drodze wielu dziwnych zmian (które jednak dają w najlepszym przypadku
3/4). Z forum trudno pojąć, czy unsigned long long int faktycznie tu
wystarcza (ludzie piszą cuda o wielu różnych typach). W związku z tym
oraz mając na celu uchronienie zainteresowanych przed gotowcem mam mały
zestaw porad dotyczących rozwiązania (4/4):

  1. Wystarczają long double oraz long long

  2. NWD pozwoliło mi otrzymać 2/4, ale na 3/4 i 4/4 potrzeba było czegoś jeszcze

  3. W zadaniu ważne jest rzutowanie, na przykład wczytanie danych
    jako long double i rzutowanie ich w pewnych miejscach na long long

  4. Wielu ludzi (a na pewno ja) usilnie starało się zmniejszać liczby
    w ułamkach sądząc, że to miał na myśli autor twierdząc, że można je
    zmieścić w 64 bitach. Niesłusznie - dla 3/5, 8/6 oraz 7/11 można
    spokojnie rozszerzyć te liczby do znacznie większych (powiedzenie jakich
    to rozwiązanie na tacy), a nie zamieniać 8/6 na 4/3, by uzyskać
    możliwie małe wartości, które potem dodawałem w jakiś tam sposób
    (postępując w ten sposób nie przeszedłem testu #2)

  5. Po odpowiednich przekształceniach, które zasugerowałem powyżej,
    okaże się, że ułamki można do siebie dodać bez żadnych problemów

  6. Suma liczników, nawet po rozszerzeniu, zmieści się w odpowiednich typach danych, o ile wykona się odpowiednie przekształcenia

  7. Rozwiązanie nie powinno zając więcej niż 100 lini kodu (wystarczy nawet około połowa).

Powodzenia!

Dlaczego usunąłem powyższy komentarz z komentarzy pod zadaniem?
Miejscem na takie wypowiedzi [i podpowiedzi] jest forum. Dajmy możliwość innym samodzielnego rozwiązywania zadania, a jeżeli już ktoś "podda się" i koniecznie będzie szukał pomocy lub gotowca, to tu jest to miejsce. Dodatkowo, wybacz Anonimowy, napisałeś w swoim komentarzu "kupę" małych głupstw i nieścisłości. Zadanie nie dlatego jest w średnich, że jest łatwe, bo nie jest. Widać to nawet z powyższego wątku i z pytania kokoska, pozostającego bez odpowiedzi aż do dziś. Tak, bo dzisiaj [dopiero] mogę definitywnie odpowiedzieć tak. W tym zadaniu, zgodnie z tym co napisał autor, wystarczy tylko i wyłącznie typ unsigned long long. A operacje skracania i doprowadzania do wspólnego mianownika, to nie żadna magia, tylko podstawowa wiedza wyniesiona z lekcji matematyki [w podstawówce?]. Deogi Anonimku, przecież typ long double nie jest typem 64 bitowym:
Uruchom w programie:
cout << "sizeof(double) = " << sizeof(double) << endl;
cout << "sizeof(long double) = " << sizeof(long double) << endl;

PS
Na pocieszenie, moje 4/4 uzyskałem prawie 4 lata temu, w podobny, karkołomny sposób, a dzisiaj twój błędny komentarz zmobilizował i zmusił mnie do przemyślenia i poprawienia go i jak napisałem użycia tylko unsigned long long i uzyskania 4/4.

PS 2
Można też użyć tylko typu long double, bez żadnych skracań i doprowadzania do wspólnego mianownika, ale należy pamiętać o skończonej dokładności [precyzji] wszystkich typów zmiennoprzecinkowych i że nie można porównywać takich wartości do zera lecz z pewnym błędem.
if (a + b <= c + 10e-15) drukuj ( NIE ) // c >= b >= a
else drukuj ( TAK )
ale i tak maks jaki udało mi się w ten sposób uzyskać to 3/4, zmieniając wartość błędu 10e-15 na mniejsze i większe wartości.

PS 3
Anonimowy. Jak na razie powinieneś brać poprawkę na swoje programy nie dwa ale trzy wink. 100 linii kodu / 3. Przecież chyba już Ci wysyłałem jakiś mój program?

Nie wiedziałem, czy wstawić to na forum czy tam, ale na nowym forum znalazłem jedynie pocięty temat ze starego forum spoja: http://213.192.104.217/phpBB3-spoj-pl-backup/viewtopic.php?f=1&t=253&sid=10feec30e00c0668b48d14a211b4c06826 . Tam kokosek w końcu dostaje maksa za to zadanie wink Uznałem, że nie będę pogłębiał różnic między jednym i drugim forum.

Odpiszę dość krótko, bo nie chciałbym wszczynać długiej i mało istotnej dla rozwiązujących to zadanie dyskusji.

Warto wiedzieć, że to zadanie można zrobić mniej karkołomnie. Możliwe (pewne?), że zabrakło w moim rozwiązaniu pomyślunku. Oczywiście na swoje kody powinienem brać poprawkę (i nic nie wróży niestety zmiany) - podałem ograniczenie górne. Nie twierdzę, że long double jest typem 64 bitowym. Także nie uzyskałem z epsilonem wyniku wyższego niż 3/4. Być może za kilka lat, o ile będzie mnie stać na prąd oraz internet, że o mieszkaniu/domu nie wspomnę, też doznam oświecenia. To tak w skrócie jeżeli chodzi o Twój post.

A teraz dlaczego napisałem ten komentarz, co myślę jest ważniejsze dla ogółu. Przyznaję, że jest on trochę na wyrost. Za zadanie to zabrałem się nie znając jeszcze dokładnie sensu zadań algorytmicznych i jego treść zinterpretowałem jako: "cokolwiek zrobisz, masz AC". Nawet nie pomyślałem o skracaniu ułamków. Z czasem jednak zauważyłem, że NWD to podstawa w zadaniach łatwych dotyczących ułamków i przeniosłem to na średnie - 2/4. Ponieważ wiele osób skuszonych pozorną prostotą próbuje sił w tym zadaniu nie mając zbyt wielkiego doświadczenia ze SPOJem uznałem, że ten komentarz może im pomóc. Inaczej mogą dojść do 3/4 a potem nie mieć pojęcia, co jest nie tak. Starałem się napisać wszystko możliwie precyzyjnie i zgodnie z prawdą a przy tym nie dać gotowca. Nie wyszło mi to najlepiej - przyznaję. Z pewnością sprawę utrudnia też mój kontakt ze środowiskiem programistycznym wyłącznie na SPOJu. W "mojej działce" wskazówki i założenia interpretuje się w zadaniach trochę inaczej, przykładowo pomijając produkty uboczne (a może ich być sporo), nierealność założeń, niewykonalność problemu itd. Mam jednak nadzieję, że mimo wszystko komuś mój komentarz pomoże.

Komentarze tego typu będę już zamieszczał na forum.

Może i tak, ale przecież Ci napisałem wyżej, że ja dopiero teraz zrobiłem to zadanie zgodnie ze sztuką i zgodnie z założeniami autora zadania, czyli doświadczyłem oświecenia;-) Fakt, że wątek dotyczący tego zadania na starym forum jest nieco dłuższy, ale z niego też nie wynika, że może oprócz jednej osoby, ktokolwiek inny zrobił to zadanie "czysto", bez wykorzystywania w "kluczowym" miejscu podpórki z long double.
Ja też, mimo, że w tamtym wątku zabierałem głos, wtedy nie, dopiero wczoraj przejrzałem na oczy, a to jest proste i banalne.
Między innymi @adam_bak, a potem

@kokosek1 [kokosek] napisał:
Rzutuję na samym końcu przy sprawdzaniu czy istnieje taki trójkąt.
Bo aby to sprawdzić trzeba dodać 2 boki i porównać z trzecim. Boki mieszczą się w uns. long longu, ale ich suma już nie

Czyli sprawdza taką nierówność:
if ( a + b > c ) to ok, można zbudować trójkąt
Jeżeli wiemy, [np posortowaliśmy], że c >= a oraz c >= b, to czy nie możemy z tym powyżej coś zrobić - innego niż rzutowanie na long double? Wiemy, że a + b > 2^64 . Przyjrzyj się tej nierówności bardzo długo i uważnie, przecież tu obowiązują zupełnie takie same reguły matematyczne jak przy równaniach.

PS
Ponieważ otwierające się przed Tobą widoki na świetlaną przyszłość są takie czarne, może chciałbyś się dowiedzieć czegoś więcej, póki jeszcze masz internet? :wink:

Już wiem, co można zrobić z tą nierównością, jeżeli wiem, jak uporządkowane są te liczby (np a > c > b) wink Dzięki wielkie za podpowiedź. Rzeczywiście, long double są niepotrzebne, choć upraszczają rozwiązanie. 4/4 na longach.

Zabawne. Gdy zrozumiałem dawno temu, że NWD nie wystarczy, próbowałem zrobić właśnie coś takiego jak teraz. Za to brak NWW dawał błędy. Potem zrobiłem NWW i zaniechałem tej metody - efektem było 3/4, ale darowałem sobie takie dość trywialne bądź co bądź rozważania (takie nierówności to chyba podstawówka). A potem znalazłem w sieci long double jako sposób na to zadanie.

Z rozmowy z Tobą mam więcej wiary w kombinowanie i lepsze zdanie o tym zadaniu. Z gotowca w sieci świetną sztuczkę z long double, fast IO (void readINT(int *n), fwrite_unlocked("TAK\n",4,1,stdout)). Sporo wiedzy przed czarną przyszłością wink

18 days later

Witam.
Mam problem z powyższym zadaniem więc podepnę się pod temat. Mianowicie mój program poprawnie "rozwiązuje" 6 przykładów z treści zadania, natomiast po wrzuceniu do sprawdzenia otrzymuję jedynie 1/4 :frowning:
Proszę o pomoc, oto mój kod: ideone20

Operujesz na dużych liczbach zmiennoprzecinkowych. Pierwsze błędy pojawiają się przy dzieleniu. Następne pojawiają się przy porównaniach. Chyba już kilka osób próbowało tak rozwiązać to zadanie, ale nie wyszło im to (0/4 do 1/4 w zależności od zastosowanej metody). Teoretycznie wprowadzenie odpowiedniej poprawki epsilon powinno pomóc, ale chyba nikt nie rozwiązał tego zadania już na początku dzieląc liczby przez siebie a potem zwyczajnie dodając je. To zadanie średnie - testy są bardzo złośliwe i zadanie jest oporne na najprostsze podejście :wink:

Z powyższej dyskusji i forum starego spoja możesz wywnioskować, że da się to zrobić na typach całkowitych przy odpowiednich manipulacjach ułamkami.

5 years later

Pisze i mówi się: testy przykładowe / przykładowe testy.

Zapewne chodzi Ci o testy #1 i #3.

Możesz wstawić kod i coś się znajdzie, ale chyba nie tędy droga w tym przypadku… .

Te dwa testy przechodziły mi, gdy wykorzystywałem GCD i LCM do rozszerzenia ułamków w celu obliczenia ich sum, ale wcześniej skracałem ułamki w danych wejściowych. Jeśli robisz coś podobnego - to stanowczo za mało. Da się jeszcze bardziej zoptymalizować.

Jeżeli już to 3 - telefon do przyjaciela.
Publiczność - ten wątek przeczytałeś cały?
Pół na pół też już masz.

SAMODZIELNA Umiejętność układania testów i testowania to podstawa. Testy w zadaniu nie są do tego - wielokrotnie to było mówione.

TAKie testy, w liczniku:
1 2 3
Lub
1 1 2
Lub
1 1 1
Zamiast 1,2 i 3 podstaw odpowiednie duże maksymalne liczby Unsigned Long long.
Podobnie w mianownikach. Mogą tam być same 1 Lub odpowiednie np max - 1

No i testy typu 3 2 1 oraz 2 1 1

Obawiam się @narbej, że w tym przypadku samodzielnie można ułożyć co najwyżej testy sprawdzające dla małych inputów, a nie dla dużych. Zgodnie z treścią zadania “(…) dane są tak dobrane, że do rozwiązania wystarczy 64-bitowy zakres zmiennych”. Jeżeli ktoś nie ma pomysłu na zadanie to znajdzie takie liczby, dla których ten zakres będzie za mały choćby nie wiem jak kombinować i wówczas tym bardziej nie znajdzie sposobu na AC.

Proponowałbym raczej rozpatrywać szczególne liczby. Np. przyjmij, że masz rozwiązać to zadanie, ale żadna wielkość pomocnicza nie może przekroczyć 16, choć dane mogą zawierać duże liczby (np. 16 / 1, 15 / 6, … ). W takim przypadku dostrzeżesz więcej zależności i więcej rzeczy policzysz na kartce. Np. nie będzie problemów z rozkładem na czynniki pierwsze, policzeniem GCD w pamięci itd.

Twoje zadanie polega na znalezieniu możliwie wielu “sztuczek”, które pozwolą zastosować nierówność trójkąta (siłą rzeczy z pewnością nie bezpośrednio) tak, by na żadnym etapie obliczeń nie przekroczyć progu wynoszącego 16.

NWW i NWD to dobry punkt wyjścia.

Najłatwiej byłoby zobaczyć kod pytającego, bo to że robi podobnie to za mało. Pytający zapomniał o słowie ostatecznie. Tzn proszę o 3 koło ratunkowe OSTATECZNIE :wink:

A które koło było lepsze dla niego? Niech powie. Piszę z telefonu, więc nie podałem na tacy testu ale może jak będę już przy kompie…

14 days later

Sam nie wiem co napisać, ale powinieneś chyba wiedzieć, że testy z zadania są tylko do oglądania, a nie do przechodzenia.
Mój poniższy program:

main {] {
cout << "
NIE
TAK
NIE
NIE
NIE
NIE
" << endl;
}

też je przechodzi zupełnie bez wysiłku - testy z zadania, i co z tego? :wink:

W twoim kodzie widzę dużo samodzielności i to jedyne dobre co widzę - jestem w końcu krótkowidzem, ale błędy może znajdziesz sam, a jakość kodu może kiedyś z czasem - jeszcze długa droga przed tobą ;=-)

taki oto np prościutki test, doklej do swojego i powiększaj i testuj i powiększaj i testuj i …testuj:

...
0/1 1/1 2/1 <--- tutaj NIE tak?
1/1000000000000 1/100000000000 1/100000000000 <--- a tutaj też czy nie, a może jakaś trzecia opcja? ;-)
...

PS
Dla ułatwienia? W twoim kodzie znalazłem 4 błędy [errors] i kilka warings [moich ostrzeżeń]