Một bài đăng trên blog về câu đố gần đây về việc tìm ra ba câu hỏi cách đều nhau dẫn tôi đến một câu hỏi stackoverflow với câu trả lời hàng đầu tuyên bố sẽ thực hiện nó trong thời gian O (n lg n). Phần thú vị là giải pháp liên quan đến bình phương một đa thức, tham khảo một bài viết mô tả cách thực hiện trong thời gian O (n lg n) .
Bây giờ, nhân đa thức thực tế giống như nhân số. Sự khác biệt thực sự duy nhất là thiếu mang. Nhưng ... việc mang cũng có thể được thực hiện trong thời gian O (n lg n). Ví dụ:
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
Vì vậy, câu hỏi của tôi là: lỗi ở đâu? Nhân số trong O (n lg n) là một vấn đề mở khổng lồ trong khoa học máy tính và tôi thực sự nghi ngờ câu trả lời sẽ đơn giản như vậy.
- Là mang sai, hay không O (n lg n)? Tôi đã tìm ra rằng lg n + 1 bit trên mỗi giá trị là đủ để theo dõi các giao dịch và thuật toán rất đơn giản Tôi sẽ ngạc nhiên nếu nó sai. Lưu ý rằng, mặc dù gia số riêng lẻ có thể mất thời gian O (lg n), chi phí tổng hợp cho gia số x là O (x).
- Là thuật toán nhân đa thức từ bài báo sai, hoặc có các điều kiện mà tôi đang vi phạm? Bài viết sử dụng một biến đổi Fourier nhanh thay vì một biến đổi lý thuyết số, có thể là một vấn đề.
- Có rất nhiều người thông minh đã bỏ lỡ một biến thể rõ ràng của thuật toán Schönhage tại Strassen trong 40 năm? Điều này dường như ít có khả năng.
Tôi thực sự đã viết mã để thực hiện điều này, ngoại trừ phép nhân đa thức hiệu quả (tôi chưa hiểu rõ về biến đổi lý thuyết số đủ). Kiểm tra ngẫu nhiên xuất hiện để xác nhận thuật toán là chính xác, vì vậy vấn đề có thể xảy ra trong phân tích độ phức tạp thời gian.
x^10 + 2x^8
? x ^ 10 chỉ một lần (x ^ 5 * x ^ 5) và x ^ 8 hai lần (x ^ 6 * x ^ 2 + x ^ 2 * x ^ 6)