Guess the number HDU - 5981 (DP)

Guess the number

 题目链接:HDU - 5981 

题意:一未知数x, 要求在[l, r]区间猜出未知数x,如果猜的数小于x,会给出提示:小了; 如果猜的数大于x,直接告诉你不对,并且在以后的猜测中,只要猜的数不是x,就只告诉你不对;问最坏情况下至少需要猜测几次?及猜测的方案数;

这个题和之前做的测试鸡蛋问题一样,只不过多了一步求方案数;

两个鸡蛋,100层楼问题链接

根据上边链接,有个结论:测试次数为k时,最多可以测出(k+1)*k/2层楼;楼层数在区间[(k-1)*k/2+1, (k+1)*k/2]时,最优解为k;

本题要在[l, r]区间猜数;也就是在(r-l+1)个数中猜数,当猜的数大时,只能再从已知的最小数开始向上逐个猜数;猜的小时,再猜第k+k-1个数;

求最优解这里不再赘述,可以直接看打开上边链接,作为参照;这里主要分析方案数;

f[n]为一共有n个数,最少需要猜的次数;

rank[x]为猜x次最多能猜出rank[x]个数;rank[x]=(x+1)*x/2;

cnt[n]表示一共n个数,总共的猜测方案;

sum[n]表示cnt的前n项和;

f[n]是由f[n]-1推出来的;

所以cnt[n]由cnt[rank[fn]-1]]~cnt[i-f[n]]推出来的;为什么???不知道~~~;

初始化cnt[0]=0, cnt[1]=1;

sum[0]=1, sum[1]=2;为什么???不知道~~~,每个sum都多一,但是求出来的cnt确是对的······


#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MX = 5e6 + 5;
const int mod = 100000073;
int f[MX],_rank[MX],cnt[MX],sum[MX];
int main(){
    for(int i=1; (i-1)*i/2<MX; i++){
    	for(int j=i*(i-1)/2+1; j<=i*(i+1)/2&&j<MX; j++)
    		f[j]=i;
    	_rank[i]=(i+1)*i/2;
	}
	cnt[0]=0, cnt[1]=1;
	sum[0]=1, sum[1]=2;
	for(int i=2; i<MX; i++){
		cnt[i]=(sum[_rank[f[i]-1]]-sum[i-f[i]-1]+mod)%mod;
		sum[i]=(sum[i-1]+cnt[i])%mod;
	}
	int l, r;
	while(~scanf("%d%d", &l, &r)){
		printf("%d %d\n", f[r-l+1], cnt[r-l+1]);
	}
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值