14 / 17
Jun 2020

Czy może ktoś mi udostępnić testy do zadania. Okropnie męczy mnie to zadanie, niby dobrze a AC brak.
Jakie są wyniki dla takich testów

1 1 2
5
0 5 85.000000
0 5 69.375000
0 5 66.481481
0 5 64.168750
0 5 64.168709

1 -1 -20
5
0 3 51.000000
0 3 54.375000
0 3 55.000000
0 3 55.499550
0 3 55.499887

-1 5 10
5
0 5 50.000000
0 5 65.625000
0 5 68.518519
0 5 70.831250
0 5 70.832812

-1 -5 -10
6
0 5 175.000000
0 5 159.375000
0 5 156.481481
0 5 154.168750
0 5 154.167188
0 5 154.166667

  • created

    Jun '20
  • last reply

    Nov '20
  • 16

    replies

  • 906

    views

  • 4

    users

  • 4

    links

Drogi Szanowny Panie Marku!

Testy do zadania, mógłby udostępnić autor zaDANia.
Ale w swoim pytaniu pokazał Pan brak zaufania do autora zadania :wink:
Do pierwszego tesztu mój program daje odpowiedzi dokładnie takie same jak załączył autor, czyli:
1
2
3
100
101
A jakie Pan uzyskał?
Ewentualnie proszę o wyniki Pana programu dla pozostałych testów.

Dziękuję za szybką odpowiedz, poniżej wyniki dla pozostałych testów.

test 2
1
2
3
100
199

test 3
1
2
3
100
200

test 4
1
2
3
100
200
500000

test 2
mam nie 199 ale 200
test 3 tak samo
test 4 mam:
1
2
3
100
200
8192

Może liczysz za dokładnie? Użyłeś long double? Ja mam “zwykłe” double. Mam na myśli wynik 199. Ostatni test jest możliwe, że źle dobrany i dlatego mamy tak drastycznie różne wyniki.

Używam double. Problem jest z dokładnością.
obliczam z dokładnością double e=0.000001
gdy zwiększę dokładność do e=0.0000001
to różnicą mam w ostatnim testu 4.

if(pole<=P+e && pole>=P-e) tak sprawdzam dokładność

Ja mam:

const double EPS = 10e-7;
inline bool isZero(double x){
	return x >= -EPS && x <= EPS;
}

Czyli jednak dokładniej - twoja druga wersja dokładności.
Nie sprawdzam różnicy między polem podanym a obliczonym, tylko między ich podwojoną wartością - nie muszę dzielić przez dwa obliczanego pola.
Pewnie wiesz jakie jest dokładnie pole dla twojego ostatniego testu? :wink: I pewnie jest to źle dobrany test.


tj abs(-925/6)
Może właśnie spróbuj nie dzielić przez dwa - obliczać 2*pole) i wtedy wynik oczekiwanego pola = 925/3 = 308.333333
a nie 154,166667 x 2 = 308,333334

EDIT
Dla tak prostej funkcji: f(x) = ax^2 + bx +c, pole w przedziale x1 = L, x2 = P można obliczyć wprost za pomocą:

Pole = 2/3aP^3 + bP^2 + 2cP - (2/3aL^3 + bL^2 + 2cL) =
lub inaczej:
Pole = fabs(2/3.0*a*(x2*x2*x2-x1*x1*x1) + b*(x2*x2-x1*x1) + 2*c*(x2-x1));

Chyba wprowadziłem Cię w błąd. Dawno robiłem to zadanie i wydawało mi się że właśnie tak je robiłem. Jednak nie.

Robiłem tradycyjnie, dzieląc przez dwa.

ALe dodatkowe pytanie, czy obliczasz pole tej powierzchni także w sposób dokładny?

pole liczę taką funkcją.
double Pole(int a, int b, int c, int xa, int xb, int n)
{
double h = (xb-xa)/(double)n;
double S = 0.0;
double podstawa_a = f(a,b,c,xa), podstawa_b;

for(int i=1;i<=n;i++)
{
	podstawa_b = f(a,b,c,xa+h*i);
	S += (podstawa_a+podstawa_b);
	podstawa_a = podstawa_b;
}
return S*0.5*h;

}

Czyli tak jak podaje autor na swoim blogu. Może nie jest to najbardziej efektywna metoda ale całkowicie poprawna.

Możliwe, że można to zadanie rozwiązać zupełnie inaczej.

Dla mnie problemem było ustalić górną i dolną granicę obliczeń.
Wiadomo, że jedną granicą będzie podział na jeden trabez, a drugą podział na jakieś_n trapezów. Rozwiązanie znajduje się pomiędzy 1 a jakieś_n. I tego rozwiązania szukamy metodą wyszukiwania binarnego. Problemem jest ustalenie czy jeden to jest górna granica czy dolna :wink: Jeżeli to rozwiążesz jesteś w domu.

Ja użyłem do tego celu:

  1. Obliczyłem dokładną powierzchnię pola - całka oznaczona jest łątwa do policzenia.
  2. Porównałem tą wartość z wartością szukaną - jest albo nadmiar albo niedomiar i wtredy mogę ustalić czy 1 to górne ograniczenie czy dolne.
  3. Narysuj funkcję -x^2 i x^2 i dorysuj jeden, a potem kilka trapezów. zobacz - pomyśl jak liczona jest powierzchnia Metodą Trapezów dla tych funkcji? Z ciągłym nadmiarem czy ciągłym niedomiarem.
  4. W zależności od wniosków w pkt 3. Podział na jeden trapez - czyli 1 - to będzie albo górna albo dolna granica.
  5. Przeciwną granicę szybko znajdziesz lub ustalasz arbitralnie np na 1000 czy 100000 - ale zby dużo może być nieefektywne. Więc może podwajając, ilość podziałów, aż obliczone pole spełni twoje oczekiwania :wink: czyli może zostać przyjęte jako granica górna [lub dolna) w stosunku do 1 trapeza.
  6. Tak naprawdę mój pkt 1 i 2 jest zbędny, Wystarczy właśnie narysować [pkt 3] i wyciągnąć wnioski.

Możliwe, że nie jest to zbyt jasne - ale chciałbym zostawić miejsce do samodzielnego przemyślenia. Jeżeli będziesz miał wątpliwości to śmiało pytaj :wink:

Ja zauważyłem, że gdy a i wartość funkcji f(xa) są jednoimienne to obliczamy całkę z nadmiarem w przeciwnym wypadku z niedomiarem.
Uwzględniłem to w obliczeniach.
Ja wyszukuję binarnie od 1 do 1000000
Zauważyłem, że gdy wyznaczam pole to rozwiązaniem chyba jest najmniejsze k, dla którego wartość pola jest “równa” P.

Nie wiem czy jest to dobra strategia? Muszę jej spróbować.

Raczej to nie ma znaczenia, a nawet powiedziałbym, że tak nie jest. Tak mi się przynajmniej wydaje.
{EDIT] Wydaje mi się, że jednak masz rację, chociaż ja dochodziłem do tego inaczej, i dlatego bez przemyślenia, napisałem to co powyżej. Sorry.

Ale można jeszcze prościej niż to opisałem. Obliczamy "nasze pole dla 1 - jednego trapezu. Jeżeli obliczone pole jest mniejsze od podanego pola P, to jedynka jest --haha, a w przeciwnym wypadku odwrotnie. W jednym wypadku druga granica - duża ilość podziału na trapezy, będzie odpowiednio [komplementarnie] dolną lub gurną granicą. Przynajmniej tak myślę, bo moje AC rozwiązanie jest dużo bardziej , zupełnie niepotrzebnie skomplikowane.
Może się też od razu okazać, że 1 to jest szukana wartość. i wtedy ok, nic nie musimy więcej robić - tzn tylko wypisać :wink:

Ja nie wiem. Mi program wylicza tą wartość, ale prawdopodobnie można to oszacować tak:
( b - a) / n < 0.000001 co po przekształceniu daje:
n < (b - a) * 1000000
max b - a = 2000 więc
n < 2’000’000’000 - mieści się w typie int 2^31 <-- :wink:

Oczywiście TLE murowane. Z drugiej strony, nie mam pojęcia jak Ty oszacowałeś i skąd Ci wyszło akurat 1’000’000 - to też stanowczo za dużo i pewnie TLE.

@mlekawski!
Może to co napisałem tutaj --> Metoda trapezów będzie chociaż w jakimś stopniu pomocne?

4 months later

Dzień dobry,

Ja podszedłem do zadania w następujący sposób:
Wiemy, że błąd E <= (x2-x1)^3 * A / (6 * k ^2), zatem k^2 <= (x2-x1)^3 * A / (6 * E), co daje nam górną granice dla k (nazwijmy ją K). Zaczynamy zatem od niej i idziemy w dół, do momentu, aż znajdziemy odpowiednią wartość k (która powinna być dość blisko). E jest obarczony błędem ±10e-7, zatem musimy od E odjąć tę wartość, żeby uzyskać jak największą górną granicę. Pytanie zatem, gdzie jest błąd w moim programie?

Testy @mlekawski przechodzi wszystkie, prócz 4.6, ta wartość jest jednak zaokrągleniem właściwej wartości pola, więc od pewnego miejsca będzie ona wychodzić dla wszystkich k, co jest sprzeczne z tym, że istnieje tylko jedna taka wartość, co nam autor obiecuje.

Kod: https://ideone.com/yazEtr3

Z góry dziękuję i pozdrawiam.

Możliwe, że to jest błędne:

 if (A < 0) //upewnienie sie, ze wspolczynnik A jest dodatni

Narysuj sobie funkcję:
-1 -1 +20
lub po twoim przekształceniu:
1 1 -20

Autor nie mówi, że funkcja nie ma miejsc zerowych. Tylko badany przedział ich nie zawiera.

Możliwe, że tylko mi się wydaje błędem, to co napisałem wyżej…

Co do samego twojego sposobu, nie wypowiem się, możliwe, że jest poprawny, Życzę powodzenia.

EDIT
W świetle powyższego, myślę, że poniższwe stwierdzenie nie musi zawsze być prawdą:

double E = P - S; //blad (zawsze P >= S)
12 days later

Nie rozumiem twojego kodu, ale dla takich danych:

1 -1 -20
5
0 3 51.000000
0 3 54.375000
0 3 55.000000
0 3 55.499550
0 3 55.499887

Twój kod wypisze: 1