• D. Game with modulo 交互题


    D. Game with modulo 交互题

    题目大意:

    题目:未知一个数 (a),让你每次猜两个数 (x) 和$ y$,若 ((xmod a)ge (ymod a)) 返回 x,否则返回 y。让你猜测次数少于60次的时候猜出数 (a)

    题解:

    交互题,这个算是我最不会写也不太想写的题目之一了。

    还是有点难的,接下来说说我看了这么多的博客之后的想法。

    img

    首先很容易的发现这个就是一个周期为a的函数,图像如上。

    所以每次找 (i) ,如果 (i*2mod\,a <=imod\,a) ,那么显然易见,在区间 ([i,i*2]) 有且仅有一个值 $xmod,a = 0 $ ,那么从小到大找到的第一个 (x),这个 (x=a)

    接下来贴一下证明:https://www.cnblogs.com/ttttttttrx/p/10800618.html

    好像不是那么容易理解,接下来我简单说说。

    • (amod \,b<a/2(a>=b))(a-b*k=x)
    • 其中 (b*k>=a/2) ,应该可以缩小成 (b*k>a/2),这个是因为如果(b*k<=a/2) ,那么 (2*b*k<=a),所以 (b*k>a/ 2), 所以 (x<a/2)
    • 所以 (amod\,b<a/2(a>=b))
    • 如果 (a<b) ,那么 (amod \,b<a/2(a>=b)) 一定不成立,因为 (amod\,b=a>a/2)
    • 综上所述,从小到大找,找到的第一个 (i*2mod\,a <=imod\,a) ,那么 (a) 一定在区间 ([i,2*i]) 之间
    • 最后说说为什么是每次找 ([2^i,2^{i+1}]) ,因为如果 ([2^{i-1},2^i]) 没有找到,说明 (2^i<a) 那么 区间 ([2^i,2^{i+1}]) 一定最多一个点 (x),使得 (xmod\,a=0)

    所以说,如果找到了一个 (i*2mod\,a <=imod\,a) ,那么 (i*2>a) 一定成立。

    这个之后就是一个二分,这个二分比较特别,因为我已经知道 (imod\,a>i*2mod\,a) ,并且 (2*i>a & i<a) ,所以我每次枚举 ([mid,r])

    如果结果是 (r),那么说明已经应该是 (r) 变小,如果结果是 (mid) 那么说明 (l) 可以变大,自行领悟吧。

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 1e3+10;
    typedef long long ll;
    char s[10];
    int main(){
        while(true){
            scanf("%s",s+1);
            if(s[1]=='s'){
                ll l = 0,r = 1;
                for(int i=1;i<=35;i++){
                    printf("? %lld %lld
    ",l,r);
                    fflush(stdout);
                    scanf("%s",s+1);
                    if(s[1]=='x') break;
                    //如果等于x,表示i mod a > i*2 mod a 
                    l = r,r <<= 1;
                }
                ll ans=0;
                while(l<=r){
                    ll mid=(l+r)>>1;
                    printf("? %lld %lld
    ",mid,r);
                    fflush(stdout);
                    scanf("%s",s+1);
                    if(mid+1==r){
                        if(s[1]=='x') ans = r;
                        //如果 mid mod a > r mod a,因为答案ans一定是 ans%a = 0,所以更小的这个应该是答案
                        else ans = mid;
                        break;
                    }
                    else if(s[1]=='x') l = mid;
                    else r = mid;
                }
                printf("! %lld
    ",ans);
                fflush(stdout);
            }
            else break;
        }
        return 0;
    }
    /*
    input
    
    start
    x
    x
    start
    x
    x
    y
    start
    x
    x
    y
    y
    end
    
    
    output
    ? 0 0
    ? 10 1
    ! 1
    ? 0 0
    ? 3 4
    ? 2 5
    ! 2
    ? 2 4
    ? 2 5
    ? 3 10
    ? 9 1
    ! 3
    
     */
    
  • 相关阅读:
    【Rust】结构体 struct
    【Rust】所有权、引用、借用
    Centos7升级glibc2.24
    ES用户权限控制
    PHP压缩html网页代码 : 清除空格,制表符,注释标记
    PHP通过HTTP_USER_AGENT判断是否为手机移动终端的函数
    php正则表达式替换URL链接地址为指定url的形式
    PHP下使用CURL方式POST数据至API接口的方法
    设计模式代理模式
    设计模式生成器模式
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/13389735.html
Copyright © 2020-2023  润新知