Sito aratostenesa optymalizacja

Sito aratostenesa optymalizacja
TA
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 37
0

Witam piszę tutaj po raz któryś. Ucze się jakiś miesiąc języka c++ (Łącznie z przerwami) i mam cały czas problem z optymalizacją kodu do jak najlepszej złożoności.

Zadanie oczywiście ze spoj-a polega na wyznaczeniu liczb pierwszych w zakresie. Problem? Przekroczono limit czasu:/

Ma ktoś wiedzę dzięki czemu mogę to lepiej zoptymalizować? Szukając w internecie znalazłem kilka innych ale prawie wszystkie bazują na tym samym.
Proszę jedynie o informacje która bilbioteka lub co może tutaj pomóc, dalej sam już znajdę nie chcę żebyście rozwiązywali problem za mnie.

Link do zadania: https://www.spoj.com/problems/PRIME1/

Kod mojego brzydala:

Kopiuj
#include <iostream>
#include <math.h>

using namespace std;


void licz(long long int &a, long long int &b)
{
    bool *zbior= new bool[b+1];
    for(int i=2; i<=b; i++)
    {
        zbior[i]=true;
    }
    for(int i=2; i<=sqrt(b); i++)
    {
        if(zbior[i]==true)
        {
            for(int j=i*i; j<=b; j+=i)
            {
                zbior[j]=false;
            }
        }
    }
    for(int i=2; i<=b; i++)
    {
        if((zbior[i]==true)&&(i>=a))
        {
            cout<<i<<endl;
        }
    }
}

int main()
{
    int proby;
    long long int zakres1,zakres2;
    cin>>proby;
    while(proby!=0)
    {
        cin>>zakres1>>zakres2;
        while((1>zakres1>zakres2>1000000000)||(zakres2-zakres1>100000))
        {
            cout<<"Zle wpisane dane, wpisz ponownie liczby musza spelniac warunki 1 <= a <= b <= 1000000000, b-a<=100000, nie rozpoczniesz zadania dopoki tego nie zrobisz."<<endl;
            cin>>zakres1>>zakres2;
        }
        licz(zakres1,zakres2);
        proby--;
    }
    return 0;
}
MarekR22
  • Rejestracja: dni
  • Ostatnio: dni
1
  1. Must read: https://dsp.krzaq.cc/post/176/ucze-sie-cxx-kiedy-uzywac-new-i-delete/
  2. gdzie w treści zadania jest napisane, że masz wypisywać: ""Zle wpisane dane, wpisz ponownie liczby musza ..... "?
  3. Sito masz policzyć RAZ, na uruchomienie aplikacji, a ty liczysz go za każdym razem, gdy dostajesz nowy zakres!
  4. To jest jedno z tych głupich zadań, gdzie operacje IO są wąskim gardłem dopisz:
Kopiuj
    std::ios::sync_with_stdio (false);
    std::cin.tie(nullptr);
TA
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 37
0

Errory przy wykorzystaniu:

Kopiuj
std::ios::sync_with_stdio (false);
std::cin.tie(nullptr);

specializing member 'std::basic_ios<char>::sync_with_stdio' requires 'template<>' syntax| <= Zupełnie nie rozumiem.
'cin' does not name a type; did you mean 'sin'?| <= Że co? Jak nie jest jak jest?

MarekR22
  • Rejestracja: dni
  • Ostatnio: dni
1

https://wandbox.org/permlink/MyBmkg2cteieMHLQ
https://wandbox.org/permlink/ZcQDH9cxLLdzAwbS

na dodatek popatrz co krzyczy kompilator:

Kopiuj
prog.cc:43:17: warning: comparisons like 'X<=Y<=Z' do not have their mathematical meaning [-Wparentheses]
   43 |         while((1>zakres1>zakres2>1000000000)||(zakres2-zakres1>100000))
      |                ~^~~~~~~~

Pewnie wpisałeś ten fragment poza funkcją stąd błedy. Może powinieneś wrócić do podstaw i książki z której korzystasz?

enedil
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1028
2
MarekR22 napisał(a):
  1. Must read: https://dsp.krzaq.cc/post/176/ucze-sie-cxx-kiedy-uzywac-new-i-delete/
  2. gdzie w treści zadania jest napisane, że masz wypisywać: ""Zle wpisane dane, wpisz ponownie liczby musza ..... "?
  3. Sito masz policzyć RAZ, na uruchomienie aplikacji, a ty liczysz go za każdym razem, gdy dostajesz nowy zakres!
  4. To jest jedno z tych głupich zadań, gdzie operacje IO są wąskim gardłem dopisz:
Kopiuj
    std::ios::sync_with_stdio (false);
    std::cin.tie(nullptr);

Zupełnie błędne rady nr 3 i 4 (czyli te istotne).
Liczba przypadków testowych to 10, a wielkość każdego zakresu to maksymalnie 10000, w którym jest maksymalnie jakoś 1500 liczb pierwszych, tak więc na wejściu będzie max 20 liczb, a na wyjściu max 15000, czyli dostatecznie mało, żeby się nie przejmować.
Rada 3: w tym zadaniu akurat robiąc sito wiele razy, osiąga się lepszy czas (tylko trzeba to robić trochę sprytnej niż autor), niż robiąc je tylko raz. Nie przemyślałeś tematu.

lion137
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 5025
2

Naiwne sito, jak zauważyli piszący w tym wątku, albo będzie za wolne, albo przekroczy limit pamięci. Spróbuj tym:
https://en.wikipedia.org/wiki/Sieve_of_Atkin
Zakresy nie są zbyt duże (100000), można zaryzykować metodę naiwną, z dobrym testem (Miller Rabin). Do miliarda to [Miller Rabin] będzie praktycznie O(1).

enedil
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1028
1

Żeby udowodnić, że się da, i to całkiem szybko, wystarczy rzucić okiem:
Imgur

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.