P2060 猜数游戏
P2060\(\mathbf{} \begin{Bmatrix} \frac{{\Large SLOJ-P2060} }{{\color{Red}\Large Solution} }\mathbf{} {No.19} \end{Bmatrix}\times{}\) NeeDna
题意
一个简单的猜数游戏,NPC 先在 \([L,R)\) 中选择一个整数,然后 由你猜数,每次 NPC 会告诉你所猜之数是大于还是小于等于原数。
另外,当大于这一情况返回 \(K\) 次时,你 便不能继续猜数了。当 你成功把数范围缩小到 \([P,P+1)\) 时即算胜利。
但 NPC 十分狡猾,他会根据你的猜测临时变更原数,使你猜数次数尽可能多,现在你采用最佳策略猜数,请算出他猜出原数的步数。
第一行三个整数 \(L\),\(R\),\(K\) 含义如上所示。
题解
发现这个题次数只和 \(L-R\) 和 \(K\) 有关,因为你要算的是一个长度下的 \(ans\) 。所以自然和 \(L\),\(R\) 的具体值无关,然后写出dp
( \(i\) 为用了多少次大于,\(j\) 为区间大小,代码里 dp 的符号顺序有点不同)
打出来发现过了??? \(2e10\) 是怎么过的,但是无需在意,优化的话第一个转移有单调性,可以用单调队列优化,但是我懒得写了。
code:
#include<bits/stdc++.h>
#define int long long
using namespace std;
int f[5010][1010],l,r,k,n;
signed main(){
memset(f,127,sizeof(f));
cin>>l>>r>>k;n=r-l;
for(int i=1;i<=n;i++) f[i][1]=i-1;
for(int i=1;i<=k;i++) f[1][i]=0;
for(int i=2;i<=k;i++){
for(int j=2;j<=n;j++){
for(int kk=1;kk<=j;kk++){
f[j][i]=min(f[j][i],max(f[kk][i-1],f[j-kk][i])+1);
}
}
}
cout<<f[n][k];
return 0;
}
AI's better code:
#include<bits/stdc++.h>
#define int long long
using namespace std;
int f[5010][1010],l,r,k,n;
signed main(){
memset(f,127,sizeof(f));
cin>>l>>r>>k;n=r-l;
for(int i=1;i<=n;i++) f[i][1]=i-1;
for(int i=1;i<=k;i++) f[1][i]=0;
for(int i=2;i<=k;i++){
int opt=1;
for(int j=2;j<=n;j++){
while(opt<j&&max(f[opt][i-1],f[j-opt][i])>=max(f[opt+1][i-1],f[j-(opt+1)][i])) opt++;
f[j][i]=max(f[opt][i-1],f[j-opt][i])+1;
}
}
cout<<f[n][k];
return 0;
}
update 2025.6.4 -- AI优化后的代码给出

浙公网安备 33010602011771号