這題是互動題,如果judge寫爛了記得告訴我。
以下是一個雙人遊戲:
二個玩家之中,有一個人當「挑戰者」,另一個人當「衛冕者」。有三個雙方都知道的正整數$N, L, M$。「衛冕者」先祕密決定一個$1$到$M$之間的正整數$u$,每次「挑戰者」要猜測一個可能的正整數$u$,「衛冕者」要如實回答當次猜測的值是小於、等於還是大於真正的$u$。若「挑戰者」在猜測$N$次之內猜中正確的$u$,且其中「衛冕者」回答「小於」的次數小於$L$,則由「挑戰者」獲勝,否則由「衛冕者」獲勝。
請根據以上敘述,回答以下二個問題:
0. 給定正整數$N, L$,已知若策略適當,則「挑戰者」一定能獲勝,求$M$的最大值?
1. 假設在第一題中,$M$的最大值以$M_0(N, L)$表示,請給出「挑戰者」在$M = M_0(N, L)$時的必勝策略?
請在程式碼開頭引入標頭檔#include "lib4658.h"。請勿進行任何輸入輸出以及實作main()函式,以免產生各種不可預期的結果。
請實作以下三個函式:
0. void init():在每筆測資評測開始時會呼叫一次,可以用來進行必要的初始化。
1. long long calc_max(int N, int L):請根據給定的$N, L$(意義如上方第0題所示),回傳第0道問題在給定的$N, L$之下的答案。只要回傳的答案錯誤,程式會自動結束,然後你會吃WA。
2. void guessing_game(int N, int L):此函式要扮演上方遊戲中「挑戰者」的角色,和評測程式進行上方遊戲一次。$N, L$由函式的參數決定,$M$則是calc_max在相同參數下的正確回傳值。請透過函式int guess(long long u)進行猜測。
int guess(long long u)的說明如下:
0. 傳入的參數$u$代表你猜測的整數。
1. 若回傳值是$0$,代表你猜測的值太小。
2. 若回傳值是$1$,代表你猜測的值太大。
3. 若回傳值是$777771449$,代表你的猜測正確,請立即結束該次guessing_game函式的執行。
4. 如果在某一次guessing_game函式的執行中,你從guess接收到了$777771449$的回傳值但繼續呼叫guess函式,程式會自動結束,然後你會吃WA。
5. 如果在某一次guessing_game函式的執行中,你已經猜了$N$次數字或是你猜了太小的數字$L$次,但還沒猜對,程式會自動結束,然後你會吃WA。
評測流程如下(測資限制將於下方說明):
0. 在每筆測資評測開始時會呼叫一次init(),之後到該筆測資評測結束都不會再次呼叫。
1. 每筆測資中,評測程式會先準備好若干組$(N, L)$,假設依次為$(N_0, L_0), (N_1, L_1), (N_2, L_2), \cdots , (N_{k - 1}, L_{k - 1})$。所有的$(N_i, L_i)$兩兩相異,且都滿足$N_i, L_i$是正整數,且$1 \le L_i \le N_i \le 67, L_i \le 20$。(顯然,在此限制下$k$有上界。)
2. 接著,評測程式會重複以下流程$k$次:假設當下的次數是第$i$次,則評測程式會先以$(N_i, L_i)$作為參數呼叫calc_max函式,然後確認回傳值正確之後,再以$(N_i, L_i)$作為參數呼叫guessing_game函式。
3. 若你在任何一個地方吃WA,則從吃WA的地方開始,後續的評測均不會執行。
以下是範例評測程式,可以複製貼上並將檔案命名為"lib4658.h",將其與你的程式放在同一個目錄下:
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void init();
ll calc_max(int N, int L);
void guessing_game(int N, int L);
namespace grader{
void wrong_answer(){
cout << "Wrong Answer\n";
exit(0);
}
void accepted(){
cout << "Accepted\n";
exit(0);
}
void validate_ans(int chances, int low, ll expected){
ll ans = calc_max(chances, low);
cout << ans << '\n';
if(ans != expected) wrong_answer();
}
ll expected;
int left_chance, left_low;
bool correct;
void simulate_game(int chances, int low, ll ans){
expected = ans, left_chance = chances, left_low = low, correct = false;
guessing_game(chances, low);
}
int guess(ll what){
cout << what << '\n';
if((--left_chance) <= 0 && what != expected) wrong_answer();
if(correct) wrong_answer();
if(what < expected){
if((--left_low) <= 0) wrong_answer();
return 0;
}
else if(what > expected) return 1;
else{
correct = true;
return 777771449;
}
}
}
int guess(ll u){
return grader::guess(u);
}
int main(){
init();
int how_many;
cin >> how_many;
for(; how_many > 0; how_many--){
int chances, low;
ll max_expected, guess_expected;
cin >> chances >> low >> max_expected >> guess_expected;
grader::validate_ans(chances, low, max_expected);
grader::simulate_game(chances, low, guess_expected);
}
grader::accepted();
return 0;
}
本題沒有輸入,此輸入說明提供範例Grader使用。
第零行是一個非負整數$k$,代表你準備了幾組$(N, L)$要測試
接著的$k$行,每一行是四個正整數,以空格分開,前兩個正整數依序是$N, L$,第三個正整數則是以該組$(N, L)$為參數呼叫calc_max的時候,你期望的回傳值,第四個正整數則是該次執行guessing_game時評測程式在遊戲中所決定的整數
$k \ge 0$
在第$1$行到第$k$行,假設某一行的四個正整數依序是$N, L, M, u$,則$1 \le L \le N \le 67, L \le 20, 1 \le u \le M$
本題沒有輸出,此輸出說明提供範例Grader使用。
評測程式會按照上方流程進行評測,對於每次評測程式呼叫calc_max以及作答程式呼叫guess會輸出一行包含一個整數,代表calc_max的回傳值或guess傳入的參數
結果產生(WA或AC)之後,評測程式會再輸出一行,代表評測結果
1 8 3 92 67
92 92 81 68 55 66 67 Accepted
0. 正式評測程式不會按照上方給的格式進行輸入輸出,所以請不要自行處理輸入輸出。
1. 範例評測程式是non-adaptive。
2. 上方給的範例輸入輸出是提供給範例評測程式使用。
原題在這裡
本題的judge是adaptive judge
| No. | Testdata Range | Constraints | Score |
|---|---|---|---|
| 1 | 0~1 | $L = 1$ | 5 |
| 2 | 2~3 | $L = N$ | 5 |
| 3 | 4~8 | 無特別限制 | 90 |