Güncel bir bulmaca blog yazısı üç eşit aralıklı olanları bulma konusunda bir götürebilir stackoverflow soru iddiaları O (n lg n) zamanında bunu yapmak için bir üst cevap. İlginç olan, çözümün bir polinomun karesini içermesi ve O (n lg n) zamanında nasıl yapılacağını açıklayan bir makaleye gönderme yapmasıdır .
Şimdi, polinomları çoğaltmak pratik olarak sayıları çoğaltmakla aynıdır. Tek gerçek fark, taşıma eksikliğidir. Ancak ... taşıma işlemleri O (n lg n) zamanda da yapılabilir. Örneğin:
var value = 100; // = 0b1100100
var inputBitCount = value.BitCount(); // 7 (because 2^7 > 100 >= 2^6)
var n = inputBitCount * 2; // 14
var lgn = n.BitCount(); // 4 (because 2^4 > 14 => 2^3)
var c = lgn + 1; //5; enough space for 2n carries without overflowing
// do apparently O(n log n) polynomial multiplication
var p = ToPolynomialWhereBitsAreCoefficients(value); // x^6 + x^5 + x^2
var p2 = SquarePolynomialInNLogNUsingFFT(p); // x^12 + 2x^11 + 2x^10 + x^8 + 2x^7 + x^4
var s = CoefficientsOfPolynomial(p2); // [0,0,0,0,1,0,0,2,1,0,2,2,1]
// note: s takes O(n lg n) space to store (each value requires at most c-1 bits)
// propagate carries in O(n c) = O(n lg n) time
for (var i = 0; i < n; i++)
for (var j = 1; j < c; j++)
if (s[i].Bit(j))
s[i + j].IncrementInPlace();
// extract bits of result (in little endian order)
var r = new bool[n];
for (var i = 0; i < n; i++)
r[i] = s[i].Bit(0);
// r encodes 0b10011100010000 = 10000
Benim sorum şu: burada hata nerede? O (n lg n) 'de sayıları çarpmak bilgisayar biliminde devasa bir açık problemdir ve cevabın bu kadar basit olacağından gerçekten şüpheliyim.
- Taşıma yanlış mı değil O (n lg n) mı? Değer başına lg n + 1 biti taşımak için yeterli olduğunu ve algoritmanın çok basit olduğunu, yanlış olsaydı şaşırırdım. Her ne kadar ayrı bir artış O (lg n) zaman alabilse de, x artışlar için toplam maliyetin O (x) olduğunu unutmayın.
- Kağıttan polinom çarpma algoritması yanlış mı yoksa ihlal ettiğim koşullar mı var? Makale, sayı teorik bir dönüşüm yerine hızlı bir fourier dönüşümü kullanıyor.
- Birçok akıllı insan 40 yıldır Schönhage-Strassen algoritmasının belirgin bir varyantını kaçırdı mı? Bu en az muhtemel görünüyor.
Aslında verimli polinom çarpma dışında bunu uygulamak için kod yazdım (henüz yeterince teorik dönüşüm yeterince anlamıyorum). Rastgele test, algoritmanın doğru olduğunu onaylar gibi görünür, bu nedenle sorun zaman karmaşıklığı analizinde olabilir.
x^10 + 2x^8
mi? x ^ 10 yalnızca bir kez (x ^ 5 * x ^ 5) ve x ^ 8 iki kez (x ^ 6 * x ^ 2 + x ^ 2 * x ^ 6)