题解 [CF1672E] notepad.exe
不大会,赛时差点做睡着了
发现 \(\sum len\) 是可以问出来的
考虑令 \(S=(\sum len)+n-1\)
这个东西就是 \(h=1\) 时最小的 \(w\),可以二分出来
那么对于一个 \(h\),有意义的 \(S'\in[S-h+1, S]\)
而且要求 \(h\mid S'\),那么在这个范围内只有一个合法的 \(w\)
则枚举取到最优解的 \(h\),只需要 check \(w=\lfloor\frac{S}{h}\rfloor\) 即可
注意边界问题,二分时左边界为 1 而非 0
复杂度 $O(n+\log2000n)
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f3f3f3f3f
#define N 100010
#define ll long long
#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n, mlen, ans=INF;
int qans(int x) {cout<<"? "<<x<<endl; fflush(stdout); cin>>x; return x;}
signed main()
{
cin>>n;
int l=1, r=5000000, mid;
int lim=qans(r);
while (l<=r) {
mid=(l+r)>>1;
if (qans(mid)==lim) r=mid-1;
else l=mid+1;
}
mlen=r+1;
for (int i=1; i<=n; ++i) {
if (qans(mlen/i)==i) ans=min(ans, mlen/i*i);
}
cout<<"! "<<ans<<endl;
fflush(stdout);
return 0;
}