zoukankan      html  css  js  c++  java
  • Codeforces Round #534 (Div. 2)D. Game with modulo-1104-D(交互+二分+构造)

    D. Game with modulo
    time limit per test
    1 second
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    This is an interactive problem.

    Vasya and Petya are going to play the following game: Petya has some positive integer number aa. After that Vasya should guess this number using the following questions. He can say a pair of non-negative integer numbers (x,y)(x,y). Petya will answer him:

    • "x", if (xmoda)(ymoda)(xmoda)≥(ymoda).
    • "y", if (xmoda)<(ymoda)(xmoda)<(ymoda).

    We define (xmoda)(xmoda) as a remainder of division xx by aa.

    Vasya should guess the number aa using no more, than 60 questions.

    It's guaranteed that Petya has a number, that satisfies the inequality 1a1091≤a≤109.

    Help Vasya playing this game and write a program, that will guess the number aa.

    Interaction

    Your program should play several games.

    Before the start of any game your program should read the string:

    • "start" (without quotes) — the start of the new game.
    • "mistake" (without quotes) — in the previous game, you found the wrong answer. Your program should terminate after reading this string and it will get verdict "Wrong answer".
    • "end" (without quotes) — all games finished. Your program should terminate after reading this string.

    After reading the string "start" (without quotes) the new game starts.

    At the beginning, your program should ask several questions about pairs of non-negative integer numbers (x,y)(x,y). You can only ask the numbers, that satisfy the inequalities 0x,y21090≤x,y≤2⋅109. To ask a question print "? x y" (without quotes). As the answer, you should read one symbol:

    • "x" (without quotes), if (xmoda)(ymoda)(xmoda)≥(ymoda).
    • "y" (without quotes), if (xmoda)<(ymoda)(xmoda)<(ymoda).
    • "e" (without quotes) — you asked more than 6060 questions. Your program should terminate after reading this string and it will get verdict "Wrong answer".

    After your program asked several questions your program should print the answer in form "! a" (without quotes). You should print the number aa satisfying the inequalities 1a1091≤a≤109. It's guaranteed that Petya's number aa satisfied this condition. After that, the current game will finish.

    We recall that your program can't ask more than 6060 questions during one game.

    If your program doesn't terminate after reading "mistake" (without quotes), "end" (without quotes) or "e" (without quotes), it can get any verdict, because it will continue reading from closed input. Also, if your program prints answer or question in the incorrect format it can get any verdict, too. Be careful.

    Don't forget to flush the output after printing questions and answers.

    To flush the output, you can use:

    • fflush(stdout) in C++.
    • System.out.flush() in Java.
    • stdout.flush() in Python.
    • flush(output) in Pascal.
    • See the documentation for other languages.

    It's guaranteed that you should play at least 11 and no more than 100100 games.

    Hacks:

    In hacks, you can use only one game. To hack a solution with Petya's number aa (1a1091≤a≤109) in the first line you should write a single number 11 and in the second line you should write a single number aa.

    Example
    input
    Copy
    start
    x
    x
    start
    x
    x
    y
    start
    x
    x
    y
    y
    end
    
    output
    Copy
    ? 0 0
    ? 10 1
    ! 1
    ? 0 0
    ? 3 4
    ? 2 5
    ! 2
    ? 2 4
    ? 2 5
    ? 3 10
    ? 9 1
    ! 3
    
    Note

    In the first test, you should play 33 games with Petya's numbers 11, 22 and 33.

    In the first game, Petya will answer "x" (without quotes) to any question, because (xmod1)=0(xmod1)=0 for any integer xx.

    In the second game, if you will ask pair (0,0)(0,0), the answer will be "x" (without quotes), because (0mod2)(0mod2)(0mod2)≥(0mod2). But if you will ask pair (2,5)(2,5), the answer will be "y" (without quotes), because (2mod2)<(5mod2)(2mod2)<(5mod2), because (2mod2)=0(2mod2)=0 and (5mod2)=1(5mod2)=1.

    题意:让你猜一个整数a,范围是[1,1e9] 你可以最多60次询问,每一次询问你可以问两个整数 x,y,如果x%a>=y%a 程序会返回一个“x”,否则返回“y”。

    思路:

    首先询问0 , 1 如果返回x,那么a一定是1,然后进入下一轮。如果返回y,那么去询问 ? 1 , 2  如果返回y

    再询问  ? 2 4

    继续 ? 4 8

    ? 8 16

    知道返回x,则证明a一定再x和y中间,然后二分[x,y]这个区间,每一次问? x  , mid这样,直到x==y结束,x和y就是答案a。

    极限数据情况下正好60次,所以算法是合理的,具体细节比较多,可以参考我的AC代码。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #include <vector>
    #define sz(a) int(a.size())
    #define all(a) a.begin(), a.end()
    #define rep(i,x,n) for(int i=x;i<n;i++)
    #define repd(i,x,n) for(int i=x;i<=n;i++)
    #define pii pair<int,int>
    #define pll pair<long long ,long long>
    #define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
    #define MS0(X) memset((X), 0, sizeof((X)))
    #define MSC0(X) memset((X), '', sizeof((X)))
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define eps 1e-6
    #define gg(x) getInt(&x)
    #define db(x) cout<<"== [ "<<x<<" ] =="<<endl;
    using namespace std;
    typedef long long ll;
    ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
    ll powmod(ll a,ll b,ll MOD){ll ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
    inline void getInt(int* p);
    const int maxn=1000010;
    const int inf=0x3f3f3f3f;
    /*** TEMPLATE CODE * * STARTS HERE ***/
    char s[maxn];
    char re[1000];
    char ask(ll j,ll k)
    {
        k=min(k,2000000000ll);
        printf("? %lld %lld
    ",j,k);
        fflush(stdout);
        scanf("%s",re);
        return re[0];
    }
    int main()
    {
        int o=-1;
        while(1)
        {
    
            scanf("%s",s);
            if(s[0]=='e'||s[0]=='m')
            {
                break;
            }else
            {
                char w=ask(0ll,1ll);
                if(w=='x')
                {
                    printf("! 1
    ");
                    fflush(stdout);
                }else
                {
                    ll j=1;ll k=2;
                    int flag=0;
                    repd(i,1,30)
                    {
                        w=ask(j,k);
                        if(w=='x')
                        {
                            flag=1;
                            break;
                        }else
                        {
                            j=k;
                            k*=2;
                        }
                    }
                    if(flag)
                    {
                        ll mid=(j+k)>>1;
                        repd(i,1,29)
                        {
                            mid=(j+k)>>1;
                            w=ask(mid,k);
                            if(w=='x')
                            {
                                j=mid;
                            }else
                            {
    
                                k=mid;
    
                            }
                        }
                        printf("! %d
    ",max(j,k));
                        fflush(stdout);
                    }
                }
    
            }
        }
        return 0;
    }
    
    inline void getInt(int* p) {
        char ch;
        do {
            ch = getchar();
        } while (ch == ' ' || ch == '
    ');
        if (ch == '-') {
            *p = -(getchar() - '0');
            while ((ch = getchar()) >= '0' && ch <= '9') {
                *p = *p * 10 - ch + '0';
            }
        }
        else {
            *p = ch - '0';
            while ((ch = getchar()) >= '0' && ch <= '9') {
                *p = *p * 10 + ch - '0';
            }
        }
    }

    本博客为本人原创,如需转载,请必须声明博客的源地址。 本人博客地址为:www.cnblogs.com/qieqiemin/ 希望所写的文章对您有帮助。
  • 相关阅读:
    数组中只出现一次的数字
    平衡二叉树
    二叉树的深度
    数字在排序数组中出现的次数
    数组中的逆序对
    第一个只出现一次的字符位置
    丑数
    把数组排成最小的数/1038. Recover the Smallest Number
    python系统编程(十一)
    python系统编程(十)
  • 原文地址:https://www.cnblogs.com/qieqiemin/p/10308600.html
Copyright © 2011-2022 走看看