Codeforces1672E. notepad.exe
传送门
\(\texttt{Difficulty:2200}\)
题目大意
一篇文章,有 \(n(1\le n\le2000)\) 个单词,要求每行放置的字符数相同,一个单词不能够分两行放置,同一行的每两个单词之间必须有一个空格,其余空出来的地方也都填上空格,每次询问 \(w\) ,回答在每行 \(w\) 个字符的情况下,放下这篇文章要 \(h\) 行,放不下则 \(h=0\) ,可以询问 \(n+30\) 次,求出能够放下文章最小的 \(wh\) 。
思路
发现我们可以很容易地二分来求出只有一行时的最小答案,记当前答案为 \(ans\) 。接下来我们可以询问其他行数下的答案,如果放置 \(i\) 行时的答案要比 \(ans\) 小,说明每行放不超过 \(\lfloor\frac{ans}{i}\rfloor\) ,如果得到的答案不为 \(i\) ,则说明不行,否则更新 \(ans\) ,即可在规定次数内得出答案。
代码
#include<bits/stdc++.h>
#include<unordered_map>
#include<unordered_set>
using namespace std;
using LL = long long;
using LD = long double;
using ULL = unsigned long long;
using PII = pair<int, int>;
using TP = tuple<int, int, int>;
#define all(x) x.begin(),x.end()
#define mst(x,v) memset(x,v,sizeof(x))
#define mk make_pair
//#define int LL
//#define lc P*2
//#define rc P*2+1
//#define endl '\n'
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#pragma warning(disable : 4996)
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
const double eps = 1e-8;
const LL MOD = 1000000009;
const LL mod = 998244353;
const int maxn = 200010;
int N;
void solve()
{
int lo = 0, hi = 1e9;
while (hi - lo > 1)
{
int mid = (hi + lo) / 2;
cout << "? " << mid << endl;
int val;
cin >> val;
if (val == 0 || val > 1)
lo = mid;
else
hi = mid;
}
int ans = hi, val;
for (int i = 2; i <= N; i++)
{
cout << "? " << ans / i << endl;
cin >> val;
if (val == i)
ans = ans / i * val;
}
cout << "! " << ans << endl;
}
int main()
{
IOS;
cin >> N;
solve();
return 0;
}