題目
IGMP 協議中,有一個字段稱作最大響應時間 (Max Response Time) ,HOST收到查詢報文,解折出 MaxResponseTime 字段后,需要在 (0,MaxResponseTime] 時間 (s) 內選取隨機時間回應一個響應報文,如果在隨機時間內收到一個新的查詢報文,則會根據兩者時間的大小,選取小的一方刷新回應時間。
最大響應時間有如下計算方式:
當 Max Resp Code < 128, Max Resp Time = Max Resp Code;
當 Max Resp Code ≥ 128,
Max Resp Time = (mant | 0x10) << (exp + 3);
注: exp最大響應時間的高5~7位: mant 為最大響應時間的低4位。
其中接收到的MaxRespCode 最大值為 255,以上出現所有字段均為無符號數。
現在我們認為 HOST收到查詢報文時,選取的隨機時間必定為最大值,現給出 HOST 收到查詢報文個數 C,HOST 收到該報文的時間T,以及查詢報文的最大響應時間字段值 M,請計算出HOST 發送響應報文的時間。
輸入描述
第一行為查詢報文個數 C,后續每行分別為 HOST 收到報文時間 T 及最大響應時間M,以空格分割。
輸出描述
HOST發送響應報文的時間。
備注
用例確定只會發送一個響應報文, 不存在計時結束后依然收到查詢報文的情況。
用例
輸入 | 輸出 | 說明 |
---|---|---|
3 ? 0 20 ? 1 10 ? 8 20 | 11 | 第0秒收到報文,響應時間為20秒(0+20=20)。 第1秒收到新報文,響應時間為1+10=11秒,因11<20,更新最小時間為11秒。 第8秒收到報文,響應時間為8+20=28秒,維持最小時間11秒。 最終結果為11秒 |
思路
題目核心在考察二進制操作和各進制互轉。主要關注 Max Resp Code ≥ 128 時怎么把響應碼轉成響應時間。mant 是響應碼低四位,怎么提取二進制的低四位?提取低四位應該是保留低四位的01狀態,把其它位的狀態值都置為0,那么與(&)上只有低四位是1其它位是0的二進制數不就保留了第四位,即 mant = code & 0b00001111(0b開頭是JavaScript表示二進制字面量的一種寫法),為了代碼寫起來簡潔,一般不直接用二進制字面量,0b00001111可以被看成掩碼,轉成十進制或十六進制不影響二進制運算。JavaScript 把二進制轉十進制需先調用變量toString(radix)方法轉為字符串,radix是進制,默認是10,再解析為數字。let b =?0b00001111,? decimal = Number(b.toString()) = 15,轉為16進制為 hex = toString(16) = 'f',寫成十六進制為 0xf 或0x0f,0x0f 是推薦十六進制字面量寫法,它包含了前導0,0x0f 能清晰地表示低 4 位為 1111,高 4 位為 0000,即二進制的 00001111。JavaScript 沒法通過函數輸出數值類型0x0f 或 0xf 形式的十六進制,只能用字符串表示,JavaScript數值表示一般都是十進制。代碼里這樣寫吧:mant = code & 15。接下來提取exp,圖片中顯示exp位于第5到第7位之間包含邊界,八位二進制從右邊第一位起計數,索引按1開始。那么提取高5~7位可以用高5~7位的狀態位都是1其余位都是0的二進制數0b01110000進行與操作,然后右移動4位把其余位沖掉,為什么要右移呢,根據題意用掩碼提取二進制中的某個部分是用它表示一個新數的,低位的0是丟棄的,故要右移把提取的部分挪到最低位。0b01110000對應十進制是112,所以 exp = code & 112,如果嫌十進制表示的112有點大,可以用十六進制0x70。有了 mant 和 exp 就可以根據公式?Max Resp Time = (mant | 0x10) << (exp + 3) 計算最大響應時間了。
參考代碼
function solution() {const C = parseInt(readline());const calculateMPT = function(code) {if (code < 128) return code;const mant = code & 15;const exp = code & 112 >> 4;return (mant | 0x10) << (exp + 3);}let result = Infinity;for (let i = 0; i < C; i++) {const [T, M] = readline().split(' ').map(Number);let mT = calculateMPT(M);result = Math.min(result, T + mT);}console.log(result);
}const cases = [`3
0 20
1 10
8 20`,
`2
0 255
200 60`
];let caseIndex = 0;
let lineIndex = 0;const readline = (function () {let lines = [];return function () {if (lineIndex === 0) {lines = cases[caseIndex].trim().split("\n").map((line) => line.trim());}return lines[lineIndex++];};
})();cases.forEach((_, i) => {caseIndex = i;lineIndex = 0;solution();
});