2010-05-09 8 views
16

Trong vòng loại Vòng loại mứt yester http://code.google.com/codejam/contest/dashboard?c=433101#s=a&a=0, có một vấn đề được gọi là Chuỗi Snapper. Từ phân tích cuộc thi, tôi đã biết vấn đề đòi hỏi bit twiddling công cụ như giải nén N bit bên phải của một số nguyên và kiểm tra nếu tất cả là 1. Tôi thấy mã của một thí sinh (Eireksten) thực hiện các hoạt động như sau:Trích xuất các bit N ở cùng bên phải của số nguyên

(((K&(1<<N)-1))==(1<<N)-1) 

Tôi không thể hiểu cách hoạt động của tính năng này. Việc sử dụng -1 có trong so sánh là gì ?. Nếu ai đó có thể giải thích điều này, nó sẽ rất hữu ích cho chúng tôi tân binh. Ngoài ra, bất kỳ lời khuyên nào về việc xác định loại vấn đề này sẽ được đánh giá cao. Tôi đã sử dụng thuật toán ngây thơ để giải quyết vấn đề này và cuối cùng chỉ giải quyết được tập dữ liệu nhỏ hơn (Mất một thời gian để biên dịch tập dữ liệu lớn hơn được yêu cầu gửi trong vòng 8 phút). Cảm ơn trước.

+3

để giúp bạn liên quan, thu hồi '10.000-1 = 9999', khoảng điều tương tự xảy ra trong hệ nhị phân – Anycorn

+0

@aaa Thật vậy !. Nó có ý nghĩa hơn bây giờ. – srandpersonia

+0

Tôi thích (k^(k + 1)) >> n –

Trả lời

21

Hãy sử dụng N = 3 làm ví dụ. Trong nhị phân, 1<<3 == 0b1000. Vì vậy, 1<<3 - 1 == 0b111.

Nói chung, 1<<N - 1 tạo một số có chữ N ở dạng nhị phân.

Hãy để R = 1<<N-1. Sau đó, biểu thức trở thành (K&R) == R. Các K&R sẽ trích xuất các bit N mới nhất, ví dụ:

 101001010 
    &  111 
    ———————————— 
    000000010 

(Nhớ lại rằng Bitwise-AND sẽ trở lại 1 trong một chữ số, nếu và chỉ nếu cả hai toán hạng có 1 trong số đó.)

Sự bình đẳng giữ nếu và chỉ khi N bit cuối cùng là tất cả 1. Vì vậy, biểu thức kiểm tra nếu K kết thúc bằng N.

+0

Cảm ơn rất nhiều vì lời giải thích và thời gian của bạn. :-) – srandpersonia

4

Ví dụ: N = 3, K = 101010

1. (1<<N) = 001000 (shift function) 
2. (1<<N)-1 = 000111 (http://en.wikipedia.org/wiki/Two's_complement) 
3. K&(1<<N)-1 = 0000010 (Bitmask) 
4. K&(1<<N)-1 == (1<<N)-1) = (0000010 == 000111) = FALSE 
+0

Cảm ơn bạn đã liên kết và giải thích :-) – srandpersonia

0

Tôi nghĩ chúng ta có thể nhận ra loại vấn đề bằng cách tính toán câu trả lời bằng tay đầu tiên, đối với một số hàng loạt các N (ví dụ 1,2, 3, ..). Sau đó, chúng ta sẽ nhận ra sự thay đổi trạng thái và sau đó viết một hàm để tự động hóa quá trình (hàm đầu tiên). Chạy chương trình cho một số đầu vào và chú ý đến mẫu.

Khi lấy mẫu, viết hàm đại diện cho mẫu (hàm thứ hai) và so sánh đầu ra của hàm đầu tiên và hàm thứ hai.

Đối với trường hợp Jam mã, chúng tôi có thể chạy cả hai chức năng đối với tập dữ liệu nhỏ và xác minh đầu ra. Nếu nó giống hệt nhau, chúng tôi có xác suất cao rằng hàm thứ hai có thể giải quyết tập dữ liệu lớn theo thời gian.

1

Tôi đã làm việc thông qua vấn đề Chuỗi Snapper và đến đây tìm kiếm giải thích về cách thuật toán twiddling bit mà tôi gặp phải trong các giải pháp đã làm việc. Tôi tìm thấy một số thông tin tốt nhưng nó vẫn còn cho tôi một thời gian tốt để tìm ra cho bản thân mình, là một chút noob.

Đây là nỗ lực của tôi trong việc giải thích thuật toán và cách tìm ra thuật toán. Nếu chúng ta liệt kê tất cả các khả năng có thể và trạng thái ON/OFF cho mỗi cá hồng trong một chuỗi, chúng ta sẽ thấy một mẫu. Với trường hợp thử nghiệm N = 3, K = 7 (3 cá hồng, 7 snaps), chúng ta thấy sức mạnh và ON bang/OFF cho mỗi cá cho mọi thứ k chụp:

  1 2 3 
    0b:1 1 1.1 1.0 0.0 -> ON for n=1 
0b:10 2 1.0 0.1 0.0 
0b:11 3 1.1 1.1 1.0 -> ON for n=1, n=2 
0b:100 4 1.0 0.0 1.0 
0b:101 5 1.1 1.0 1.0 -> ON for n=1 
0b:110 6 1.0 0.1 0.1 
0b:111 7 1.1 1.1 1.1 -> ON for n=2, n=3 

Các bóng đèn là khi tất cả cá hồng đang bật và nhận nguồn, hoặc khi chúng ta có k lần chụp thứ k kết quả là n 1s.Thậm chí đơn giản hơn, bóng đèn bật khi tất cả các thiết bị bật tắt được BẬT, vì tất cả chúng đều phải nhận nguồn điện để BẬT (và do đó là bóng đèn). Điều này có nghĩa cho mỗi k snaps, chúng ta cần n 1s. Hơn nữa, bạn có thể lưu ý rằng k là tất cả các số nhị phân 1 không chỉ cho k = 7 thỏa mãn n = 3, mà còn đối với k = 3, satisifes n = 2 và k = 1 có giá trị là n = 1. Hơn nữa, đối với n = 1 hoặc 2, chúng ta thấy rằng mọi số lượng snaps bật bóng đèn, n chữ số cuối của k luôn là 1. Chúng ta có thể cố gắng khái quát rằng tất cả ks thỏa mãn n snappers sẽ là số nhị phân kết thúc bằng n chữ số 1.

Chúng ta có thể sử dụng các biểu ghi nhận của một tấm áp phích sớm hơn 1 < < n - 1 luôn mang đến cho chúng tôi n chữ số nhị phân 1, hoặc trong trường hợp này, 1 < < 3-1 = 0b111. Nếu chúng ta xử lý chuỗi các snappers của chúng ta như là một số nhị phân trong đó mỗi chữ số đại diện cho on/off, và chúng ta muốn n chữ số của một, điều này cho chúng ta đại diện của chúng ta.

Bây giờ chúng tôi muốn tìm những trường hợp 1 < < n - 1 là tương đương với một số k kết thúc bằng chữ số n nhị phân trong tổng số 1, mà chúng tôi làm bằng cách thực hiện một Bitwise-và: k & (1 < < n - 1) để lấy n chữ số cuối của k, và sau đó so sánh số đó với 1 < < n - 1.

Tôi cho rằng kiểu suy nghĩ này tự nhiên hơn sau khi làm việc với các loại vấn đề này, nhưng nó vẫn đáng sợ với tôi và tôi nghi ngờ tôi sẽ tự mình đưa ra giải pháp như vậy!

Đây là giải pháp của tôi trong perl:

$tests = <>; 
for (1..$tests) { 
    ($n, $k) = split//, <>; 
    $m = 1 << $n - 1; 
    printf "Case #%d: %s\n", $_, (($k & $m) == $m) ? 'ON' : 'OFF'; 
}