洛谷 CF1999G1 Ruler (easy version) 题解

洛谷 CF1999G1 Ruler easy version 题解

题目传送门

做法

什么,只让十次!让我好好想想。
经过一系列思考,我们发现, 2 10 = 1024 ≈ 999 2^{10} = 1024 \approx 999 210=1024999,考虑 l o g 2 log_2 log2 级别的算法,这让我们想到了二分答案。
可以二分最后一个测量正确的位置,显然,对于答案左面的部分测量都是正确的,否则是错误的,因此可以二分。
设二分左端点为 l l l,右端点为 r r r,二分的中间点为 m i d mid mid
二分的时候,如果当前测量错误,则答案只能出现在 l l l ~ m i d − 1 mid - 1 mid1 的范围内,因此 r = m i d − 1 r = mid - 1 r=mid1;如果当前测量正确,则答案只能出现在 m i d mid mid ~ r r r 之间,所以 l = m i d l = mid l=mid
询问时,我们把一边长度定为 1 1 1,另一边长度定为 m i d mid mid,这样得到的面积就是结果。
最终 x = x = x= 答案 + 1 + 1 +1,写个代码交上去。

#include <iostream>
#include <cstring>
#include <algorithm>
 
using namespace std;
 
int main()
{
	int T;
	scanf("%d", &T);
	while (T -- )
	{
		int l = 1, r = 998;
		while (l < r)
		{
			int mid = l + r >> 1;
			printf("? 1 %d\n", mid);
			fflush(stdout);
			
			int x;
			scanf("%d", &x);
			if (x == -1) return 0;
			if (x == mid + 1) r = mid - 1;
			else l = mid;
		}
		
		printf("! %d\n", l + 1);
	}
	
	return 0;
}

在这里插入图片描述
what!
不会有人把这个代码复制交上去WA了吧。
我们 d e b u g debug debug 一下。
我们先来模拟一下交互库。我们假定 x = 153 x = 153 x=153,试一下。
在这里插入图片描述
咦,竟然卡在了 152 152 152,再试一个数 473 473 473
在这里插入图片描述

又卡在了 472 472 472

经过漫长的研究,我们发现,在 x = 153 x = 153 x=153 时会以这样的形式死循环。
l = 152 , r = 153 l = 152, r = 153 l=152,r=153
m i d = 152 mid = 152 mid=152
返回结果 = m i d = mid =mid
l = m i d = 152 l = mid = 152 l=mid=152
l = 152 , r = 153 l = 152, r = 153 l=152,r=153

473 473 473 会这样卡住
l = 472 , r = 473 l = 472, r = 473 l=472,r=473
m i d = 472 mid = 472 mid=472
返回结果 = m i d = mid =mid
l = m i d = 472 l = mid = 472 l=mid=472
l = 472 , r = 473 l = 472, r = 473 l=472,r=473

观察我们的代码,每次 m i d = l + r 2 mid = \frac{l + r}{2} mid=2l+r,但如果我们把 l + r 2 \frac{l + r}{2} 2l+r 变成 l + r + 1 2 \frac{l + r + 1}{2} 2l+r+1 就没有这样的问题了。

于是有了代码。

代码

#include <iostream>
#include <cstring>
#include <algorithm>
 
using namespace std;
 
int main()
{
	int T;
	scanf("%d", &T);
	while (T -- )
	{
		int l = 1, r = 998;
		while (l < r)
		{
			int mid = l + r + 1 >> 1;
			printf("? 1 %d\n", mid);
			fflush(stdout);
			
			int x;
			scanf("%d", &x);
			if (x == -1) return 0;
			if (x == mid + 1) r = mid - 1;
			else l = mid;
		}
		
		printf("! %d\n", l + 1);
	}
	
	return 0;
}

在这里插入图片描述

结语

有的时候发现了问题,动手试一下,有时就能找到问题所在。

  • 16
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值