Guess the number HDU - 5981 (dp推理)

Guess the number HDU - 5981

 AOA just met a problem when he attended an interview, as shown below:
A and B two people play guessing games. A thinks of a number x between a and b randomly in his mind, and he lets B to guess this number. A will say too small if B’s guess is less than x and A will say yes if B’s guess is just x.Once B’sguess is bigger than x,A won't speak any more.After that,A just nods his head if B’s guess is just x,otherwise shakes his head.The problem is that how many kinds of best guess strategies to make the least number of guesses in the worst situation?

Input
Input contains multiple sets of test data and each of them occupies one line,including two integersa, b(1≤a≤b≤5 * 10^6),on behalf of range of the number.Input to the end of the file.
Output
For each set of input, output one line containing two integers. The first one represents the least number of times of guessing in the worst situation. The second one represents the number of best guess method modulo 100000073.
Sample Input

1 5

Sample Output

3 3

Hint

B can guess the number in A's mind up to 3 times in the worst case.
The first method,B can guess in the order of (2,4,5)
The second method,B can guess in the order of (3,4,5)
The third method,B can guess in the order of (3,5)
Each method is up to three times.
题意:

A和B玩一个游戏:A在[L,R]之间随机选取一个数X,之后由B来猜这个数,如果猜的数比X小,
则A就告诉B你猜的数小了,如果猜的数等于X则游戏结束,如果猜的数大于X,则在这之后A只会回答B
是否猜对了,而不会告诉B是否猜小了。问:在最坏的情况下,B猜到X时最少需要猜多少次,并输出方案数

题解:

这道题其实有一道一模一样的题目:有n层楼,2颗鸡蛋,鸡蛋有个强度:可以在第X层楼摔下去且不
会碎,要求用这2颗鸡蛋测试X是哪一层楼。

微软面试题

假设需要k次测试就能测完,那么我们该如何进行测试呢?因为第一颗蛋碎了,第二颗就只能一层一层地往上
试。因此第一次测试时,就应该选择第k层进行测试,如果在第k层碎了,则从第1层开始遍历到第k-1层,一共
需要k次;如果在第k层没有碎,那么还剩k-1次,我们就选择在k+k-1层进行测试,然后一直进行下去。

计算下来,进行k次测试,最高可以测试的层数为:k+(k-1)+…+1=k(k+1)/2

可以用数组f[x]记录有x层时需要测试的次数,状态转移的方法见代码注释

coed:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 5e6+5;
const int mod = 100000073;
/****
f[x]:有x层楼时需要测试的次数
p[x]:从p[x]楼开始测时至少需要x次测试
cnt[x]:有x层楼时的方案数
sum[x]:cnt的前缀和
****/
int f[maxn],p[maxn],cnt[maxn],sum[maxn];
int main(){
    for(int x = 0,index = 1; index < maxn;){
        //如果x * (x + 1) / 2 < index说明楼层为index时,x次不足以测出,但是可以记录下从        index层开始测最少需要测x+1次,因为x次不到index层
        //然后x+1后肯定就大于等于楼层index了,因为如果不大于等于说明公式求出的不是最大楼层,与前面分析相矛盾
        if(x * (x + 1) / 2 < index) p[++x] = index; 
        //只有x * (x + 1) / 2 >= index时x次是可以测出
        f[index++] = x;
    }
    cnt[1] = sum[0] = 1;
    sum[1] = 2;//目前没搞懂为啥这样初始化望大家指点
    /****
    设现在有x层楼,需要进行f[x]次测试,那么它的方案一定是从f[x]-1次转移过来的,
    我们设变量楼层y,有f[y] = f[x] - 1,很明显有p[f[x]-1] <= y < p[f[x]]
    通过上面分析,如果测试次数有k次,那么第一次可以选择第k层
    因此第x层可以由第[x-k,x-1]之间的楼层层转移过来,但是由于策略最优,因此上界为p[f[x]]-1
    所以第x层的方案数就等于[x-f[x],p[f[x]]-1]之间的楼层的方案数之和
    ****/
    for(int i = 2; i < maxn; i++){
        int st = i - f[i];//相当于上面的i-k
        int ed = p[f[i]] - 1;
        cnt[i] = (sum[ed] - sum[st-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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值