Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Wyznaczanie modulo z ciągu fibonacciego

Ostatnio zmodyfikowano 2017-11-07 19:00
Autor Wiadomość
pekfos
» 2017-11-03 21:58:54
C/C++
pot_szybkie( a, n / 2 ) * pot_szybkie( a, n / 2 )
Poważnie? Przypomnij, po co chcesz coś tu optymalizować, skoro twoje szybkie potęgowanie jest rząd wielkości wolniejsze niż powinno?
P-166444
jatoprzechuj
Temat założony przez niniejszego użytkownika
» 2017-11-03 22:22:45
Taka zmiana pomoże?
C/C++
template < typename M >
M pot_szybkie( M a, unsigned int n )
{
    if( n % 2 == 1 ) return a * pot_szybkie( a, n - 1 );
    else
    {
        Matrix_2x2 pol = pot_szybkie( a, n / 2 );
        return( pol * pol );
    }
P-166445
mateczek
» 2017-11-04 08:59:51
rozumiem iż Monika90 miała rację i źle podałeś treść zadania ?? podałeś  (1 ≤ n,m ≤ 109) a powinno być  (1 ≤ n,m ≤ 10^9)??

2 chcesz obliczyć 'n' elementy ciągu korzystając z właściwości macierzy
 |1 1|^n
 |1 0|
3 zdajesz sobie sprawę iż szablony czy funkcje nie działają magicznie??. i szablon nie sprawi iż z automatu program zadział gdy natrafi na działanie (macierz%int) czy (int * macierz)!!!
4 zdajesz sobie sprawę iż w c++(korzystając ze standardowych typów danych) ostatnim elementem ciągu jaki jesteś w stanie policzyć to fib(94) Tym samym nie policzysz nic więcej poza
 |1 1|^94
 |1 0|

5 masz policzyć fib(n)%m czy wzory które znalazłeś dla liczb (szybkie potęgowanie modularne) będą prawdziwe dla macierzy ?? czy to są te wzory które potrzebujesz?? nie wiem nie sprawdzałem. Komputer Ci nie wykona z automatu działania A%m jeśli "A" to macierz

6 rekurencyjne algorytmy są z reguły wolne. poniższy to już mistrzostwo świata dodanie 42 liczb i dobre 10s na moim pc
C/C++
#include<iostream>
using namespace std;
unsigned long long fib( int a )
{
    if( a == 0 ) return 0;
   
    if( a == 1 ) return 1;
    else if( a > 1 )
    {
       
        return fib( a - 1 ) + fib( a - 2 );
    }
}
int main() {
    cout << fib( 42
    );
   
}
[ cpp ]
P-166447
garlonicon
» 2017-11-04 11:48:42
Dlaczego operacja pomnożenia dwóch macierzy miałaby być szybsza, niż zwykłe dodawanie i odejmowanie dwóch zmiennych? Korzystając z macierzy trzymasz cztery zmienne, z czego dwie odnoszą się do tego samego wyrazu ciągu fibonacciego. Może lepiej kombinuj ze zwykłymi zmiennymi. Załóżmy, że masz dwa kolejne wyrazy ciągu fibonacciego oraz że obie wartości są mniejsze od
m
. Aby otrzymać dwie kolejne wartości, wystarczy napisać:
C/C++
int a = 0, b = 1;
a += b;
if( a >= m ) a -= m;

b += a;
if( b >= m ) b -= m;
Dwa dodawania, dwa odejmowania i dwa wyrażenia warunkowe. Wątpię, aby macierze cokolwiek tutaj przyspieszyły. Poza tym, korzystając z powyższego algorytmu uzyskujesz dwie wartości naraz i nie potrzebujesz żadnych zmiennych pomocniczych.
P-166449
mateczek
» 2017-11-04 12:19:12
pewnie chodzi o takie działanie które obniża ilość iteracji dla wielkich wykładników
x^16 normalnie 16 operacji
ale można w trzy operacje
y=x*x;
z=y*y;
wynik=z*z;
Ale nie wiem jak tam w te macierze modulo wkręcić. 
P-166451
jankowalski25
» 2017-11-04 14:27:45
Dobra, spróbuję z macierzami. Przechowujesz w niej trzy kolejne wartości ciągu fibonacciego, więc wystarczą trzy zmienne zamiast czterech. Na razie udało mi się podnieść taką macierz do kwadratu korzystając z dwóch zmiennych pomocniczych, ale pewnie da się prościej.
C/C++
int a = 0, b = 1, c = 1;
int d = a + c;
int e = b * b;
a *= a;
c *= c;
a += e;
c += e;
b += d;
W ten sposób w zmiennej
b
 znajdzie się dwa razy dalszy wyraz ciągu fibonacciego, czyli na przykład dla:
C/C++
a = fib( 7 );
b = fib( 8 );
c = fib( 9 );
wynikiem końcowym będzie:
C/C++
a = fib( 15 );
b = fib( 16 );
c = fib( 17 );
Takie coś działa na pewno jeśli
b
 jest 2n-tym wyrazem ciągu fibonacciego. W pozostałych przypadkach to będzie prawda, jeśli poniższe wyrażenie będzie prawdziwe:
C/C++
( fib( 2 * n - 1 ) == fib( n - 1 ) * fib( n - 1 ) + fib( n ) * fib( n ) ) &&
( fib( 2 * n ) == fib( n ) *( fib( n - 1 ) + fib( n + 1 ) ) ) &&
( fib( 2 * n + 1 ) == fib( n + 1 ) * fib( n + 1 ) + fib( n ) * fib( n ) )
Możliwe, że to zawsze wynosi
true
, jeszcze nie rozpisałem tego matematycznie na kartce. Niestety, nadal nie mam pomysłu, jak dołożyć tutaj modulo, żeby to było względnie szybkie.
P-166455
Luq
» 2017-11-04 15:53:49
C/C++
#include <iostream>
#include <cstring>

struct Matrix2x2 {
    int nums[ 2 ][ 2 ];
   
    Matrix2x2() {
        std::memset( nums, 0, sizeof( nums ) );
    }
};

Matrix2x2 MultiplyWithMod( const Matrix2x2 & one, const Matrix2x2 & two, int mod ) {
    Matrix2x2 result;
    for( int i = 0; i < 2; ++i ) {
        for( int j = 0; j < 2; ++j ) {
            for( int k = 0; k < 2; ++k ) {
                result.nums[ i ][ j ] += one.nums[ i ][ k ] * two.nums[ k ][ j ];
            }
            result.nums[ i ][ j ] %= mod;
        }
    }
   
    return result;
}

Matrix2x2 FastMatrixPowWithMod( const Matrix2x2 & mat, int power, int mod ) {
    if( power < 2 )
         return mat;
   
    Matrix2x2 half = FastMatrixPowWithMod( mat, power / 2, mod );
    if( power % 2 == 0 )
         return MultiplyWithMod( half, half, mod );
    else
         return MultiplyWithMod( half, MultiplyWithMod( half, mat, mod ), mod );
   
}

int main() {
    std::cout << /*f(90)=*/ 2880067194370816120 % 83 << '\n';
    Matrix2x2 mat;
    mat.nums[ 0 ][ 0 ] = mat.nums[ 0 ][ 1 ] = mat.nums[ 1 ][ 0 ] = 1;
    std::cout << FastMatrixPowWithMod( mat, /*90-1=*/ 89, 83 ).nums[ 0 ][ 0 ] << '\n';
}

Myślę, że coś w tym stylu powinno przejść.
P-166462
mateczek
» 2017-11-04 20:11:02
@luk. spoko powinno grać. Ja nie wiedziałem jak się zachowa mnożenie macierzy gdy wyciągnie się Modulo z każdego elementu po wymnożeniu. Ale wydaje się działać :)
P-166475
1 2 3 4 5 « 6 » 7
Poprzednia strona Strona 6 z 7 Następna strona