คำนวณ Hamming Distance จากโจทย์ Programming.in.th
โจทย์
ความยาก ★★★☆☆
นิยาม Hamming distance คือจำนวนบิตที่แตกต่างกันในเลขฐานสองระหว่างการเทียบ 2 เลข เช่น กับ มี Hamming distance เป็น 2 เพราะต่างกันที่บิตแรกและบิตสุดท้าย
โจทย์จะให้ค่า มาให้ อยากรู้ว่าผลรวม Hamming distance สำหรับเลขฐานสองที่มี หลักของ กับ เมื่อ มีค่าตั้งแต่ ถึง คือเท่าไหร่
ข้อมูลนำเข้า บรรทัดแรก ระบุจำนวนเต็ม () แทนจำนวนหลักของเลขฐานสองและช่วงของค่าที่ดู
ข้อมูลส่งออก แสดงค่าผลรวมของ Hamming distance
ตัวอย่างข้อมูลนำเข้าและข้อมูลส่งออก
Input | Output |
---|---|
3 4 | 7 |
คำอธิบายตัวอย่างแรก:
และ แปลว่าเราต้องดูเลข หลัก ตั้งแต่ จนถึง ที่คำนวณได้ดังนี้
- และ มี Hamming Distance เท่ากับ
- และ มี Hamming Distance เท่ากับ
- และ มี Hamming Distance เท่ากับ
- และ มี Hamming Distance เท่ากับ
ทำให้ผลรวมของ Hamming Distance ทั้งหมด เป็น
วิเคราะห์โจทย์
การหา Hamming Distance
หา Hamming Distance ของเลข 2 ตัวเนี่ย เราต้องการรู้แค่ว่ามีบิตที่ต่างกันกี่ตัว ดังนั้นเราสามารถทำ xor bit
ใส่เลขทั้งสองตัวได้
ในผลลัพธ์ของแต่ละบิตจะเป็นว่า ถ้าบิตของทั้งสองเลขต่างกัน ในผลลัพธ์ก็จะเป็น แต่ถ้าเหมือนกันจะเป็น ดังนั้นโจทย์ก็จะเปลี่ยนเป็นว่าหาว่ามีบิต 1 กี่ตัวแทน
ทีนี้โจทย์ก็จะเหลือแค่ นับจำนวนเลข ในผลลัพธ์ ซึ่งทำได้ใน หรือ แล้วแต่ว่าจะ implement ยังไง
แต่ถ้าไปอ่าน Constraint ใหม่ จะเห็นว่า เป็นได้ถึง ซึ่งมันเยอะไป ค่อยๆทำทีละคู่ไม่ได้เพราะจะไม่ทันเวลาเอา
ข้อสังเกต
โจทย์ไม่ได้ถามหา Hamming Distance ของเลขมั่วๆ แต่เป็นทุกคู่ตัวเลขที่ติดกันเท่านั้น ดังนั้นเราไม่จำเป็นต้องใช้วิธีคำนวณที่รองรับทุกรูปแบบตัวเลขก็ได้
ทีนี้สังเกตเพิ่มว่า การที่ค่า Hamming Distance เท่ากับ หมายความว่าจะมีทั้งหมด บิตที่แตกต่างกัน ซึ่งแต่ละบิตเนี่ยเราสามารถคิดแยกจากกันได้ แล้วการที่ Hamming Distance เพิ่มขึ้นมา 1 ได้นั้นมาจากการเทียบเลข ที่มีบิตที่มีค่าอันนึงเป็น 0 และอีกอันเป็น 1 ถ้าเรามาดู pattern แยกทีละบิตก็จะเห็นว่า
- บิตที่ 1 จะเห็นว่าบิตจะแตกต่างกันทุกครั้งเลย สังเกตตอนคำนวณ 0,1 หรือ 1,2 หรือ 2,3 หรือทุกครั้งที่ ที่หารด้วย 1 ลงตัว(ก็คือทุกครั้งแหละ 🤣) เพราะบิตนี้จะสลับ 0 กับ 1 ในการบวกทุกครั้ง
- บิตที่ 2 จะแตกต่างกันในกรณีที่มีค่า 1,2 หรือ 3,4 หรือ 5,6 หรือ ที่หารด้วย 2 ลงตัว เพราะบิตนี้จะสลับ 0 กับ 1 ในการบวกทุกๆ 2 ครั้ง
- บิตที่ 3 ก็จะต่างกันในตอนที่มีคำนวณค่า 3,4 หรือ 7,8 หรือ 11,12 ก็คือเมื่อ ที่หารด้วย 4 ลงตัว เพราะบิตนี้จะสลับ 0 กับ 1 ในการบวกทุก 4 ครั้ง
จากการลองทดดูจะสังเกตได้ว่าสำหรับบิตที่ ใดๆ บิตนี้จะแตกต่างกันตอนที่เราเทียบ กับ เมื่อ หารด้วย ลงตัว
ดังนั้นเราสรุปได้ว่าถ้าคิดแค่บิตที่ จะมีทั้งหมด คู่ที่แตกต่างกัน ซึ่งเราสามารถคำนวณได้ใน ได้เลย
ประกอบเป็นคำตอบ
โจทย์ของเราก็จะลดรูปเหลือแค่ผลรวมของจำนวนเลขที่หารลงตัวด้วย มีทั้งหมดกี่ตัว ซึ่งหาได้จากการ loop บวกตรงๆ ของ ได้ ทำให้ทำได้ใน
Challenge
- ถ้าเปลี่ยนเป็นถามได้ 100000 ครั้ง และแต่ละครั้งให้ค่า เป็นได้ตั้งแต่ ถึง จะแตกต่างจากวิธีเดิมยังไงบ้าง
- ต่อจากข้อ 1 ถ้า จะแตกต่างจากวิธีในข้อ 1 ยังไงได้บ้าง