CF1028G Guess the number

27 篇文章 0 订阅
17 篇文章 0 订阅

Description

Solution

  • 首先考虑一下为什么能够查询到一个 1 0 16 10^{16} 1016的数。
  • 对于一个区间 [ l , r ] [l,r] [l,r],我们最多查询 m i n ( l , 1 e 4 ) min(l,1e4) min(l,1e4)个数,一开始只能够查询一个数(避免个数太多),显然如果查询出来是在 m i d + 1 mid+1 mid+1后,我们之后可以使用的个数就更多了,因此感受一下第一次操作前一半很短,后一半很长,关键是怎么求出这个长度。
  • 不难想到一个dp,计 f [ l ] [ c ] f[l][c] f[l][c]为以 l l l为区间左端点,查询 c c c层,最大能够满足的右端点是什么,而对于 l > 1 e 4 l>1e4 l>1e4的全部都与 1 e 4 1e4 1e4相同。
  • 算出来发现 f [ 1 ] [ 5 ] f[1][5] f[1][5]就是那个大数(刚好就是上界)。
  • 然后直接尽量选长的,模拟即可。
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<map>
#define ll long long
#define maxn 10005
using namespace std;

ll g[6];
ll F(ll x,int c){
	if (x>=10000) return x+g[c]-1;
	if (c==1) return x+min(x,10000ll);
	ll v=min(x,10000ll)+1; x--;
	for(int i=1;i<=v;i++)
		x=F(x+1,c-1);
	return x;
}

ll d[maxn];
void doit(ll x,int c){
	ll v=min(x,10000ll)+1,s=x; x--;
	if (c==1){
		for(int i=1;i<=v;i++) x++,d[i]=x;
	} else {
		for(int i=1;i<=v;i++)
			x=F(x+1,c-1),d[i]=x;
	}
	printf("%lld ",v-1);
	for(int i=1;i<=v-1;i++) printf("%lld ",d[i]);
	printf("\n"),fflush(stdout);
	int k; scanf("%d",&k);
	if (k==-1) exit(0);
	if (k==0) doit(s,c-1); else 
		doit(d[k]+1,c-1);
}

int main(){
	freopen("ceshi.in","r",stdin);
	g[1]=10001;for(int i=2;i<=4;i++)g[i]=g[i-1]*10001;
	doit(1,5);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值