Algorytm


14

Załóżmy, że podano różnych liczb całkowitych , takich, że dla pewnej stałej i dla wszystkich .na1,a2,,an0aiknk>0i

Interesuje nas znalezienie zliczeń wszystkich możliwych sum . ( jest dozwolone).Sij=ai+aji=j

Jednym z algorytmów jest skonstruowanie wielomianu stopnia , i obliczenie jego kwadratu za pomocą metody transformacji Fouriera i odczytanie mocy z ich współczynniki w wynikowym wielomianu. Jest to algorytm czasu .P(x)=j=1nxajknO(nlogn)

Mam dwa pytania:

  • Czy istnieje algorytm , który nie korzysta z FFT?O(nlogn)

  • Czy znane są lepsze algorytmy (tj. )? (FFT dozwolone).o(nlogn)


Dlaczego tak ważne jest, aby nie używać FFT? Wygląda na to, że masz już dobre rozwiązanie swojego problemu. Skąd bierze się wymóg nieużywania FFT? Wydaje mi się, że jest to raczej nienaturalny wymóg.
DW

@DW: Ponieważ wtedy nie będzie pytania? :-) Jestem ciekawy, czy istnieje inne podejście.
Aryabhata

Ok, rozumiem! Przyznaję, że też jestem ciekawy. :-) Dziękuję za interesujące pytanie.
DW

@DW: Nie ma za co :-)
Aryabhata

Odpowiedzi:


8

Wydaje się, że ten problem jest równoważny kwadratowi całkowitemu / wielomianowemu:

1. Wiadomo, że mnożenie wielomianowe jest równoważne mnożeniu liczb całkowitych .

2. Oczywiście, zredukowałeś już problem do kwadratu wielomianowego / całkowitego; dlatego ten problem jest co najwyżej tak trudny jak wyprostowanie.

Teraz zredukuję kwadrat całkowity do tego problemu:

Załóżmy, że masz algorytm:

F(a)P2(x),where P(x)=aiaxai

Ten algorytm jest zasadniczo algorytmem, o który prosisz w swoim pytaniu. Tak więc, jeśli mam magiczny algorytm, który może to zrobić, mogę wykonać funkcję która wyrówna liczbę całkowitą y ( o tak, kocham mathjax: P ):SQUARE(y)y

Algorithm 1 Squaring1.:procedure SQUARE(y):2.:a() a starts as empty polynomial sequence3.:i04.:while y0 do break y down into a polynomial of base 25.:if y & 1 then if lsb of y is set6.:aai append i to a (appending xi)7.:end if8.:ii+19.:yy1 shift y right by one10.:end while11.:P2(x)F(a) obtain the squared polynomial via F(a)12.:return P2(2) simply sum up the polynomial13.:end procedure

Python ( test przy pomocy codepad ):

#/cs//q/11418/2755

def F(a):
    n = len(a)
    for i in range(n):
        assert a[i] >= 0

    # (r) => coefficient
    # coefficient \cdot x^{r}
    S = {}
    for ai in a:
        for aj in a:
            r = ai + aj

            if r not in S:
                S[r] = 0

            S[r] += 1

    return list(S.items())

def SQUARE(x):
    x = int(x)

    a = []
    i = 0
    while x != 0:
        if x & 1 == 1:
            a += [i]
        x >>= 1
        i += 1

    print 'a:',a
    P2 = F(a)

    print 'P^2:',P2

    s = 0
    for e,c in P2:
        s += (1 << e)*c
    return s

3. Zatem kwadratowanie jest co najwyżej tak trudne, jak ten problem.

4. Dlatego kwadratowanie liczb całkowitych jest równoważne temu problemowi. (każda z nich jest co najwyżej tak trudna ze względu na ( 2 , 3 , 1 ))

O(nlogn)O(nlognloglogn)O(nlogn2O(logn))Ω(nlogn)

O(nlogn)

5. Teraz twój problem nie polega na mnożeniu, lecz na kwadracie. Czy kwadratura jest łatwiejsza? Cóż, jest to otwarty problem (na razie nie) : nie wiadomo, że w kwadracie występuje szybszy algorytm niż mnożenie. Jeśli możesz znaleźć lepszy algorytm dla swojego problemu niż użycie mnożenia; to prawdopodobnie byłby przełom.

O(nlogn)O(nlogn)O(nlogn)O(nlogn) albo, ponieważ najlepszy algorytm mnożenia zbliża się tylko do tej złożoności.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.