SPOJ - PRIME_T oraz FCTRL3 - błędna odpowiedź

0

Witam po długiej nieobecności :)
Od pewnego czasu rozwiązuję różne zadania z SPOJ. Niestety, mam problem z dwoma zadaniami. Pomimo tego, że programy zwracają prawidłowy wynik, sędzia zwraca "błędna odpowiedź". W czym może tkwić problem? Proszę o pomoc.

Liczby pierwsze (wiem, że mogłem zastosować jakiś lepszy algorytm) - link:

#include <iostream>
#include <string>

int main()
{
    int number;
    bool is_input_right=false;
    //int t=1;
    std::string check;

    while(!is_input_right)
    {
        std::cin>>check;

        for(int i=0; i<static_cast<int>(check.size()); ++i)
        {
            if(!isdigit(check[i]))
            {
                is_input_right=false;
                break;
            }
            else
            {
                is_input_right=true;
            }
        }

        if(!is_input_right) continue;
        else number=std::stoi(check);

        if(number<=1)
        {
            is_input_right=false;
        }
        else
        {
            is_input_right=true;
        }
    }

    check.clear();

    for(int i=2; i<number; ++i)
    {
        if((number%i)==0)
        {
            std::cout<<"NIE"<<std::endl;
            exit(0);
        }
    }

    std::cout<<"TAK"<<std::endl;

    return 0;
}

Dwie cyfry silni - link:

#include <iostream>
#include <string>

class Zadanie
{
    int n;
    int silnia;

    public:
    void setN(int n);
    void licz_silnie();
    void cyfry();
};

void Zadanie::setN(int n)
{
    this->n=n;
}

void Zadanie::licz_silnie()
{
    int temp=1;
    for(int i=1; i<=this->n; ++i)
    {
        temp*=i;
    }
    this->silnia=temp;
}

void Zadanie::cyfry()
{
    //std::cout<<silnia<<std::endl;
    std::string silnia_inna_postac=std::to_string(this->silnia);
    int poz_d=static_cast<int>(silnia_inna_postac.size())-2;
    int poz_j=static_cast<int>(silnia_inna_postac.size())-1;
    poz_d<0 ? std::cout<<0 : std::cout<<silnia_inna_postac[poz_d];
    std::cout<<" "<<silnia_inna_postac[poz_j]<<std::endl;
}

int main()
{
    Zadanie z1;
    bool is_right=false;
    std::string input;

    while(!is_right)
    {
        std::cin>>input;
        
        for(int i=0; i<static_cast<int>(input.size()); ++i)
        {
            if(!isdigit(input[i]))
            {
                is_right=false;
                break;
            }
            else
            {
                is_right=true;
            }
        }

        if(!is_right)
        {
            continue;
        }

        int test=stoi(input);
        if(test<1 || test>30)
        {
            is_right=false;
        }
        else
        {
            z1.setN(test);
        }

    }

    input.clear();

    z1.licz_silnie();
    z1.cyfry();

    return 0;
}
0

Problem z zadaniem SPOJ?
Zasada numer jeden: podaj teść zadania, najlepiej link do zadania.

za znakami ```, które rozpoczynają blok z kodem, dodaj cpp, żeby pokolorowało dobrze kod.

Mimo braku treści widać na czym polega problem.
Gdzie w treści zadania masz napisane, że masz wypisać "Prosze o podanie liczby wiekszej niz 1"?.
SPOJ to jest automat, masz mu odpowiedzieć dokładnie jak opisuje zadanie. Wszelkie "dekoracje" będą powodować błędną odpowiedź.

0

Treść posta już poprawiona.
Pomimo wywalenia z kodu wszelkich "ozdobników", sędzia wciąż nie chce uznać mojego rozwiązania.

0

zadanie 1 https://pl.wikipedia.org/wiki/Sito_Eratostenesa
zadanie 2 podpowiedź 1: nie licz dosłownie silni, bo wyjdzie ci poza zakres int licz tylko ostatnie cyfry.
zadanie 2 podpowiedź 2: policz na kartce kilka pierwszych odpowiedzi i dojdź do ciekawego wniosku

0

Rada związana z testowaniem zadan: skompiluj pierwszy program i przekieruj na jego wejście dane z przykladu ze spoja:

3
11
1
4

oraz wyjście do pliku txt np. out.txt. Sprawdź czy plik out.txt jest identyczny dla wyjścia z przykładu.

0

Wybaczcie, że odpowiadam dopiero teraz. Zadanie z silnią udało mi się rozwiązać :) Niestety, wciąż mam problem z liczbami pierwszymi. Napisałem cały program od nowa (tym razem z użyciem sita Eratostenesa - program najpierw wyznacza liczby pierwsze, które potem są użyte do sprawdzenia, czy dzielą moją liczbę). Zrobiłem kilka testów. Input jest zgodny z instrukcją (liczba testów oraz kolejne liczby). Output się zgadza, mimo to sędzia odrzuca moje rozwiązanie ("Błędna odpowiedź"). Postanowiłem też sprawdzić program w CodeWars - Sample Test wychodzi pozytywnie, ale próba zgłoszenia rozwiązania skutkuje wyświetleniem błędu).

Kod programu:

#include <iostream>
#include <vector>
#include <cmath>

bool isPrime(int num)
{
    std::vector<bool> prime_or_not((num+1), true);
    int special=0;

    if(num==1) return false;
    if(num>1)
    {
        for(int i=2; i<=sqrt(num); ++i)
        {
            if(prime_or_not[i]==true)
            {
                for(int j=pow(i,2)+special*i; j<=num; ++j)
                {
                    prime_or_not[j]=false;
                    special++;
                }
            }
        }
    }


    for (int k=2; k<=sqrt(num); ++k)
    {
        if(prime_or_not[k]==true)
        {
            if(num%k==0)
            {
                return false;
                break;
            }
        }
    }
    return true;
} 

int main()
{
    int tries;
    std::cin>>tries;
    std::vector<int> numbers;

    for(int i=0; i<tries; ++i)
    {
        int input;
        std::cin>>input;
        numbers.push_back(input);
    }

    for(int j=0; j<tries; ++j)
    {
        if(isPrime(numbers[j]))
        {
            std::cout<<"TAK"<<std::endl;
        }
        else
        {
            std::cout<<"NIE"<<std::endl;
        }
    }

    numbers.clear();

    return 0;
}
0

Sito masz policzyć tylko raz na samym początku programu.
Potem dla każdego pytania sprawdzasz odpowiedź w tablicy uzyskanej z sita.
A jeśli wyciągnie się twoją implementację sita do osobnej funkcji, to ona nie działa: https://wandbox.org/permlink/E2QDifgnbMQmDmUY

Nie używaj przy tym liczb zmiennoprzecinkowych. Zabraniam ci używać sqrt i pow.
Skąd ci się wzięło to special?

0

FCTRL3

const char * const resonableResults[] {
    "0 1\n", // 0
    "0 1\n",
    "0 2\n", // 2
    "0 6\n",
    "2 4\n",
    "2 0\n", // 5
    "2 0\n",
    "4 0\n", // 7
    "2 0\n",
    "8 0\n",
    "0 0\n", // 10
};

const char *resultForFactorial(size_t x)
{
     x = std::min(x, std::size(resonableResults) - 1);
     return resonableResults[x];
}

int main()
{
    size_t n, x, i;
    std::cin >> n;
    for (i=0; i<n; ++i) {
        std::cin >> x;
        std::cout << resultForFactorial(x);
    }
    return 0;
}
0

@MarekR22 Wprawdzie jakiś czas temu rozwiązałem ten problem, ale z chęcią sprawdzam Twój kod.
Jeśli dobrze rozumiem, funkcja > resultForFactorial działa w ten sposób, że za indeks podstawia wprowadzoną na wejściu liczbę lub liczbę 10, w zależności od tego, która jest mniejsza. Ja rozwiązałem to w inny sposób, poprzez switch.

W kwestii liczb pierwszych - zastosowałem się do Twojej rady i stworzyłem oddzielną funkcję dla sita. Inicjalizowana jest poprzez największą wprowadzoną liczbę. Wprowadziłem też małą poprawkę, dzięki której sito działa zgodnie z założeniem.

Oba zadania zostały zaliczone. Wielkie dzięki za pomoc ;)

0

Co do pierwszych, to pierwiastek z 10 tys (maksymalna wartość wg specyfikacji) wynosi 100, więc starczy sprawdzić przez pierwsze mniejsze od 100 (bo 100 nie jest liczbą pierwszą) czyli

int tab[26] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101};

0

@sig jako, że liczba zapytań to 1000000 to sito do 10000 powinno szybsze.

0

Chyba że zrobi tablicę bool, to chyba będzie najszybsze rozwiązanie (w końcu liczba zapytań jest większa od zakresu liczb, czyli się powtarzają).

1 użytkowników online, w tym zalogowanych: 0, gości: 1