Algorytm konkursowy

Algorytm konkursowy
Q9
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 14
0

Witam, od jakiegoś czasu męczę się z pewnym problemem, mianowicie chodzi o program który na wejściu dostaje liczbę 0<<x<<2^32 i następnie potęguje liczbę 11 do potegi którą otrzymał na wejsciu. Program z wyniku potegowania zlicza wszystkie wystepujace w nim jedynki. Napisałem ten program, ale działa on poprawnie do momentu kiedy potega liczby 11 nie jest wieksza od 17. Gdy jest wieksza od 17 to w wyniku pojawiają się same zera. Ktoś mógłby mi pomóc ?

Załączam program:

Kopiuj
#include <stdio.h>
#include <conio.h>
#include <math.h>

int main(){

            char liczba[256];
            int i=0,j=0,potega=0;
            double wynik=0;

            printf("Witaj! Program policzy ilosc jedynek w dowolnej potedze liczby 11!\n\nPodaj potege:");
            scanf("%d",&potega);

            wynik=pow(11,potega);

            printf("\n\nOtrzymano liczbe %lf\n\n",wynik);

            sprintf(liczba,"%lf",wynik);    // KONWERSJA LICZBY DOUBLE DO TABLICY ZNAKOW ( KAZDA CYFRA TO JEDEN ZNAK!!! ) //

            for(i=0;i<potega+2;i++){

                                    if(liczba[i]==49) j++;        // W KODZIE ASCII ZNAK LICZBY 1 MA WARTOSC 49 //

                                    }

            printf("W liczbie wystepuje %d jedynek.",j);

            _getch();

            } 
_13th_Dragon
  • Rejestracja: dni
  • Ostatnio: dni
1

Zrób sobie tabelkę dla tych 11 potęg który możesz otrzymać i rozejrzyj się za regułą która te dane łączy.

Xitami
  • Rejestracja: dni
  • Ostatnio: dni
1

11<sup>{2</sup>{32}} to spora liczba, ma ponad 4 giga cyfr.
11<sup>{297} nie mieści się w double, a już 11</sup>{16} policzysz źle.
pow() nie pomoże w niczym!

Q9
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 14
0

No właśnie ... rozpisując ja żadnej regularności nie widzę... Nie mam żadnej koncepcji jak to wykonać

Xitami
  • Rejestracja: dni
  • Ostatnio: dni
1

samodzielne napisanie mnozenia dowolnie wielkiej liczby przez 11 nie jest trudne. na poczatek trzymaj w tablica odzienie każdą cyfre. później zmien na 8

Q9
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 14
0

No ok, wsadzic osobno kazda cyfre do tablicy. Na poczatku w tablicy jest zatem 1,1 ,załóżmy ze potęgą jest 56 wiec mam wykonać pętle for, która przeleci 55 razy mnożąc i zapisując osobno każdą cyfrę. Jak wymnozyc poszczegolne cyfry tak aby powstał wynik zapisany tak ze kazda jego cyfra to osobne miejsce w tablicy ?

MA
  • Rejestracja: dni
  • Ostatnio: dni
1

Mnożenie składa się z dwóch części:
najpierw mnożysz każdą cyfrę przez 11 i zapisujesz w tym miejscu w którym była, np:
liczba:
5,7,2
mnożymy przez 11:
55,77,22
i następnie przesuwasz kolejne dziesiątki od prawej do lewej:

  1. 55, 77, 22
  2. 55, 77 + 2, 2
  3. 55, 79, 2
  4. 55 + 7, 9, 2
  5. 62, 9, 2
  6. 6, 2, 9, 2
    Przydadzą Ci się do tego operatory % oraz /
agilob
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 148
0

Musisz wyjść poza standardowe biblioteki oferujące liczby.
Proponuję http://gmplib.org/
Gdzie poziom precyzji możesz ustawić ręcznie, a tutaj http://en.wikipedia.org/wiki/GNU_Multiple_Precision_Arithmetic_Library#Example jest przejrzysty przykład użycia.

bogdans
  • Rejestracja: dni
  • Ostatnio: dni
0

@qwerty9, celem programu jest wyliczenie odpowiedniej potęgi liczy 11 i policzenie ile jest w niej jedynek, czy tylko policzenie ile jest jedynek?

Q9
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 14
0

policzenie ile jest jedynek w danej potędze 11
Sposób Marseel jest bardzo dobry, tylko czy można tworzyć tak duże tablice ?

KA
  • Rejestracja: dni
  • Ostatnio: dni
0

Edit: nvm, moj blad, bzdury same tuta byly :)

Q9
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 14
0

Excel ma ten sam mankament co moj pierwotny program, mianowicie przy 16 potedze zaczyna pokazywac zera na koncu...

Xitami
  • Rejestracja: dni
  • Ostatnio: dni
0

mój skromny Atom 1.6 GHz potrzebował 41 sekund by policzyć, że 11^{100\ 000} ma 104 140 cyfr, w tym 10 190 jedynek.
program naiwny i samodzielny w 40 linijkach.

Q9
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 14
0

Napisałeś program tak, że każda cyfra to osobne miejsce w tablicy ?

Xitami
  • Rejestracja: dni
  • Ostatnio: dni
0

wcześniej zebrałem po 6, a teraz zrobiłem jak radziłem wcześniej czyli po 8 cyfr w int i mam czas 29 sekund.
czyli liczę w układzie nie dziesiętnym, za podstawę przyjąłem układ o podstawie 100 000 000
bo 99 999 999 * 11+99 999 999 "mieści" się w int

Q9
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 14
0

Twoje myślenie znacznie wykracza poza możliwości mojego umysłu, nie wiem o co chodzi :|

JA
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Białystok
  • Postów: 258
0

http://webcache.googleusercontent.com/search?q=cache:gVAcdWKGxL8J:main.edu.pl/user.phtml%3Fop%3Dlesson%26n%3D32+&cd=4&hl=pl&ct=clnk&gl=pl
Strona chwilowo padła, ale jak wróci to poczytaj sobie. W każdym razie słowo klucz - własna arytmetyka.

Xitami
  • Rejestracja: dni
  • Ostatnio: dni
0

kiedy mnożysz na papierze, nie wstawiasz do słupka bezpośredniego wyniku mnożenia dwu cyfr, tylko bierzesz mod 10 (czyli najmniejszą cyfrę iloczynu tych cyfr) (oczywiście trzeba pamiętać o przeniesieniu)
a tu nie 10 tylko 100 000 000,
zamiast 8 bajtów mamy 4, ale pośrednich mnożeń jest 8 razy mniej.

Q9
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 14
0

Przepraszam za moje nieogarnianie ale dalej nie wiem o co Ci chodzi. Sam skleciłem cos takiego ale to nie ma prawa działać bo nie mozna takich tablic deklarować:

Kopiuj
#include <stdio.h>
#include <conio.h>
#include <math.h>

int main(){
            long int liczba[4294967297],potega,i=0,przesuniecie,pozostanie,rozbicie;

            printf("Podaj potege: ");
            scanf("%d",&potega);

            liczba[0]=1;
            liczba[1]=1;

            for(i=0,i<potega,i++){

                                    liczba[i]=liczba[i]*11;

                                    }

            for(i=potega-1;i>0;i--){

                                    przesuniecie=liczba[i]/10;
                                    pozostanie=liczba[i]%10;
                                    liczba[i]=pozostanie;
                                    liczba[i-1]=liczba[i-1]+przesuniecie;

                                    }

            rozbicie=liczba[0]%10;
            przesuniecie=liczba[0]/10;

            for(i=0;i<potega+1;i++){

                                    liczba[i+1]=liczba[0];

                                    }

            liczba[0]=przesuniecie;
            liczba[1]=rozbicie;

            _getch()

            }
 
Q9
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 14
0

Poddaję się.

merlinnot
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Wrocław
  • Postów: 292
0

Och, to nie powinno być trudne, jeżeli wymyślisz sobie fajny sposób kodowania jak największej ilości cyfr w incie. Możesz to po prostu zrobić trójkątem pascala, odpowiednie wiersze to kolejne potęgi 11:

user image

Lub możesz pomyśleć o tym tak, że (11x) = (10+1)x i korzystać ze wzorów skróconego mnożenia:

user image

Q9
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 14
0

Ale chcąc zrobić to trójkątem lub dwumianem to i tak muszę stworzyc ogromną tablice. Problem w tym ze nie potrafie takiej zrobic, lub robie to złym sposobem.
Muszę przecież każdą cyfre zapisac osobno prawda ?

merlinnot
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Wrocław
  • Postów: 292
0

Kilka postów wyżej masz podany link do strony z pięknym opisem tego, jak należy się do tego zabrać, masz nawet napisane operatory. ctrl+c, ctrl+v. Implementacją tego, o czym mówił Xitami możesz spokojnie zająć się później, kiedy będziesz miał wstępnie działający algorytm.

msm
  • Rejestracja: dni
  • Ostatnio: dni
0

Widzę że się poddałeś, więc co mi tam, ja nic nie tracę, masz gotowca (znalezione gdzieś na dysku, nie pisane teraz).

Jakby co to nie mam pojęcia dlaczego, kiedy, jak, dla kogo i po co to kiedyś pisałem, ale prawdopodobnie to robiłem pijany o 4 w nocy patrząc na kod który jest lekkim WTF (szczególnie define i komentarz na początku - tak było w oryginale O_o)...

Tak czy inaczej, być może Ci w czymś pomoże, chociaż wątpię żeby otrzymanie gotowego kodu w czymkolwiek pomagało...

Kopiuj
using namespace std;

#define private public
// pure insane madness

#include <iostream>
#include <stdint.h>

typedef uint32_t chunk_t;
typedef uint64_t chunk_dbl_t;

class bigNum
{
private:
    static const chunk_t THRESHOLD = 1000; 

    chunk_t *chunks;
    size_t used_chunks;
    size_t allocated_chunks;

public:
    bigNum(int);
    bigNum(chunk_t *, int);
    bigNum operator*(const bigNum &);

    size_t estimateProductSize(const bigNum &, const bigNum &);
};

bigNum::bigNum(int value)
{
    this->chunks = new chunk_t[1];
    this->chunks[0] = value;
    this->used_chunks = 1;
    this->allocated_chunks = 1;
}

bigNum::bigNum(chunk_t *chunks, int numChunks)
{
    this->chunks = chunks;
    this->used_chunks = numChunks;
    this->allocated_chunks = numChunks;

    while(!this->chunks[this->used_chunks - 1])
    { this->used_chunks--; }
}

size_t bigNum::estimateProductSize(const bigNum &n1, const bigNum &n2)
{
    return n1.used_chunks + n2.used_chunks;
}

bigNum bigNum::operator*(const bigNum &other)
{
    size_t newSize = bigNum::estimateProductSize(*this, other);
    chunk_t *newChunks = new chunk_t[newSize];
    memset(newChunks, 0, newSize * sizeof(chunk_t));

    for(size_t i = 0; i < this->used_chunks; i++)
    {
        chunk_dbl_t carry = 0;
        for(size_t j = 0; j < other.used_chunks; j++)
        {
            chunk_dbl_t product = this->chunks[i] * other.chunks[j];
            product += newChunks[i + j] + carry;
      
            newChunks[i + j] = product % THRESHOLD;
            carry = product / THRESHOLD;
        }
        newChunks[i + other.used_chunks] = carry;
    }

    return bigNum(newChunks, newSize);
}

bigNum naivePow(int num, uint32_t pow)
{
    bigNum value = num;
    bigNum result = 1;

    for(uint32_t i = 0; i < pow; i++)
    {
        result = result * value;
    }

    return result;
}

bigNum basicFastPow(bigNum num, uint32_t pow)
{
    if (pow == 0) { return 1; }
    if (pow % 2 == 0) 
    { 
        bigNum tmp = basicFastPow(num, pow / 2);
        return tmp * tmp;
    }
    else
    {
        bigNum tmp = basicFastPow(num, (pow - 1) / 2);
        return num * tmp * tmp;
    }
}

int countOnes(const bigNum &n)
{
    int ct = 0;
    for(size_t i = 0; i < n.used_chunks; i++)
    {
        chunk_t chk = n.chunks[i];
        while(chk)
        {
            if (chk % 10 == 1) { ct++; }
            chk /= 10;
        }
    }
    return ct;
}

int main()
{
    int n;
    cin >> n;
    bigNum n1 = basicFastPow(11, n);
    cout << countOnes(n1) << endl; 
}
Xitami
  • Rejestracja: dni
  • Ostatnio: dni
0

potęgi 11 raczej palindromami nie są

Kopiuj
0       1
1       11
2       121
3       1331
4       14641
5       161051
6       1771561
7       19487171
8       214358881
9       2357947691

Jakoś nie podoba mnie mi się sposób trójkątno pascalowy.
(1+10)<sup>n=\sum_{k=0}</sup>{n}\left(\begin{array}{c}n\k\end{array}\right)10<sup>{n-k} nie mnożymy przez 10</sup>{n-k} to tylko "przesunięcie" przy sumowaniu, suma nie do n, tylko do około n/2, ale każdy krok to mnożenie i dzielenie długiej przez krótką,
w porównaniu do pojedynczego mnożenia długiej przez krótką
jakoś nie podoba mi się, niby operuje się liczbami krótszymi ale..., no nie podoba mi się

Xitami
  • Rejestracja: dni
  • Ostatnio: dni
0

naiwne potęgowanie, podstawa systemu to 2^32, Atom'ek policzył:
9 sek. dla 100'000
36 sek. dla 200'000
80 sek dla 300'000
143 sek. dla 400'000
ile można się spodziewać dla 2'000'000'000 ? gdzieś około 114 lat :-)
moja potęga to unsigned int w[464317052]; to trochę mniej niż 2 GB.

dla porównania, coś nie naiwnego:

Kopiuj
PARI/GP (mechanika GMP)
 gp > 11^ 10 000 000;                 time =  3,829 ms.
 gp > 11^ 50 000 000;                 time = 25,297 ms.
 gp > 11^100 000 000;                 time = 50,297 ms.
 gp > 11^150 000 000;                 time = 1mn, 17,484 ms. 
 gp > 11^200 000 000;            *** _^s: length (lg) overflow
Q9
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 14
0

Na początku nie wspomniałem iż językiem ma być c a nie c++.

merlinnot
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Wrocław
  • Postów: 292
0

To zamień sobie iostream na stdio.h i ciny na scanfy :)

Azarien
  • Rejestracja: dni
  • Ostatnio: dni
0
marseel napisał(a):

Mnożenie składa się z dwóch części:
najpierw mnożysz każdą cyfrę przez 11 i zapisujesz w tym miejscu w którym była, np:
liczba:
<ciach>
Przydadzą Ci się do tego operatory % oraz /

a nie prościej dopisać 0 na końcu i dodać n? przyda się operator dodawania ;-)

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.