zoukankan      html  css  js  c++  java
  • Codeforces 1114E(简单交互)

    这里有一道老实题,大家快来踩爆它!

    交互题:根据你的输出决定下一次的输入。

    请听题:

    管理员有个乱序数列(举例:{14, 24, 9, 19}),排序以后是个等差数列({9, 14, 19, 24}),现在他只告诉你有n个数(样例n = 4)却不给你数列,让你求出最小的那个数(9)和公差d(5)。

    而你可以在不超过60次的询问之后再给出结果,询问有两种方式:

    1.    输出“> x”,暗示是否存在大于x的数,如果存在,管理员回复“1”,否则回复“0”。(这个回复自己读入一下谢谢~)

    2.    输出“? i”,请求查询乱序数列第i个数是几,然后管理员会告诉你哒。

    最后你得到结果后最终输出“! minnum d”。

    样例:

    input:

    4

    (注意以下输入数据是对应你的输出的)

    0

    1

    14

    24

    9

    19

    output:
    > 25(之后有了输入0)

    > 15(之后有了输入1)

    ? 1 (之后有了输入14)

    ? 2

    ? 3

    ? 4

    ! 9 5(这个就是答案了)

    题解:

    头一次遇到这么简单的E题大家自己AC吧全剧终。

    好,大家A掉了以后我来分享一下我做这个题的思路历程:

    首先自鸣得意地想到如果数列长度不足60那在下岂不是厚着脸皮问出来就行了……于是有了下面这段代码:

     1 void work1() {
     2     for (int i = 1; i <= n; i++) {
     3         printf("? %d
    ", i);
     4         fflush(stdout);
     5         scanf("%d", &a[i]);
     6     }
     7     sort(a + 1, a + 1 + n);
     8     printf("! %d %d
    ", a[1], a[2] - a[1]);
     9 }
    10 
    11 int main() {
    12     scanf("%d", &n);
    13     if (n <= 60)    work1();

    然后果然这段代码是没卵用的,还是要想个更一般的方法。

    那么根据这题的询问模式我们不难意淫到这样一个场景:你让心仪的妹子心中默念一个1~2147483647的数字,因为不忍心拒绝激动而又熟稔地背出一串奇怪数字的你,正在和吴彦祖聊天的妹子于是默念520。好的君已入瓮,你遂使出了(非)计算机专业引以为傲的“二分莽猜之术”猜了二三十次以后猜到了答案并说了出来,然后……

    然后AlphaWA过来问你可以用这种方法得到最小值咩?啊不能。but问个log1e9(≈30)次总能得到个最大值了对吧?

    好,好。30是60的一半,这路子很稳。有了最大值和项数,根据小学奥数知识我们不难搞出最小值了。

    那么剩下的30次询问怎么用呢?可以得到其中的一些数喽。于是有了以下思考历程:

    1.    用30次可以抽到(排序后)连续的两个数吗,这样公差d就出来了?欧皇可,非酋不可。

    2.    那能搞到第二大的值吗,道理同上?回答同上。

    3.    emmm那随便来几个数,有什么办法搞到d?唔,他们的差一定是d的倍数,gcd一遍就好啦!

    4.    稳吗?不稳,比如2,4,6,8,10,12,我们如果抽到4,8,12,会得到d = 4这一错误结果。

    5.    所以根据大数据的原理(大雾),数字越多错误率越低,且请随机抽取,免得有规律抽取被一些居心不良的红名同学出一组针对数据hack掉。

    嗯,那就做完了。参考代码,请无视掉:小家子气的60以下特判、写1024次1024个模样的二分、未使用mt19937的乡下随机。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 int n, d, maxx;
     5 int a[65];
     6 bool mark[1000005];
     7 
     8 int random(int n) {
     9     return (double)rand()/RAND_MAX * n + 0.5;
    10 }
    11 
    12 void work1() {
    13     for (int i = 1; i <= n; i++) {
    14         printf("? %d
    ", i);
    15         fflush(stdout);
    16         scanf("%d", &a[i]);
    17     }
    18     sort(a + 1, a + 1 + n);
    19     printf("! %d %d
    ", a[1], a[2] - a[1]);
    20 }
    21 
    22 int main() {
    23     scanf("%d", &n);
    24     if (n <= 60)    work1();
    25     else {
    26         int l = 0, r = 1e9, cnt = 0;
    27         while (l < r) {//二分莽猜
    28             int mid = (l + r) >> 1;
    29             printf("> %d
    ", mid);
    30             fflush(stdout);
    31             cnt++;
    32             scanf("%d", &d);
    33             if (d)    l = mid + 1, maxx = l;
    34             else    r = mid;
    35         }
    36         //随机序列
    37         srand(time(0));
    38         for (int i = cnt + 1; i <= 60; i++) {
    39             d = 0;
    40             do {
    41                 mark[d] = true;
    42                 d = random(n) + 1;
    43             } while (mark[d]);
    44             printf("? %d
    ", d);
    45             fflush(stdout);
    46             scanf("%d", &a[i]);
    47         }
    48         sort(a + cnt + 1, a + 61);
    49         //gcd
    50         d = a[cnt+2] - a[cnt+1];
    51         for (int i = cnt + 3; i <= 60; i++) {
    52             d = __gcd(d, a[i] - a[i-1]);
    53         }
    54         printf("! %d %d
    ", maxx - (n-1) * d, d);
    55     }
    56     return 0;
    57 }

    奉上御用std:

     1 #pragma comment(linker, "/stack:247474112")
     2 #pragma GCC optimize("Ofast")
     3 
     4 #include <bits/stdc++.h>
     5 using namespace std;
     6 
     7 #define endl '
    '
     8 mt19937 rng32(chrono::steady_clock::now().time_since_epoch().count());
     9 
    10 int n, Max = -1000000000, d = 0;
    11 int queryRemaining = 60; vector<int> id;
    12 
    13 void findMax() {
    14     int top = -1000000000, bot = +1000000000;
    15     while (top <= bot) {
    16         int hasHigher;
    17         int mid = (top + bot) / 2;
    18         cout << "> " << mid << endl;
    19         fflush(stdout); cin >> hasHigher;
    20         queryRemaining--;
    21         if (hasHigher) top = mid + 1;
    22         else {bot = mid - 1; Max = mid;}
    23     }
    24 }
    25 
    26 void findD() {
    27     vector<int> List; int RandomRange = n;
    28     while (queryRemaining > 0 && RandomRange > 0) {
    29         int demandedIndex = rng32() % RandomRange;
    30         cout << "? " << id[demandedIndex] << endl; fflush(stdout);
    31         int z; cin >> z; List.push_back(z);
    32         RandomRange--; queryRemaining--;
    33         swap(id[demandedIndex], id[RandomRange]);
    34     }
    35     sort(List.begin(), List.end());
    36     if (List.back() != Max) List.push_back(Max);
    37     for (int i=1; i<List.size(); i++) {
    38         d = __gcd(d, List[i] - List[i-1]);
    39     }
    40 }
    41 
    42 void Input() {
    43     cin >> n; id.resize(n);
    44     for (int i=0; i<n; i++) id[i] = i+1;
    45 }
    46 
    47 void Solve() {
    48     findMax(); findD();
    49     int Min = Max - d * (n - 1);
    50     cout << "! " << Min << " " << d;
    51     cout << endl; fflush(stdout);
    52 }
    53 
    54 int main(int argc, char* argv[]) {
    55     ios_base::sync_with_stdio(0);
    56     Input(); Solve(); return 0;
    57 }
  • 相关阅读:
    Solr6.6环境安装及core的创建(win7环境)
    使用Druid作为数据源
    Windows远程数据同步工具cwRsync
    解读zookeeper的配置项
    堵塞与非堵塞原理
    Apache Hadoop2.0之HDFS均衡操作分析
    转到简书去了
    淘宝技术这十年概要
    Facebook广告API系列 Business Manager
    Facebook广告API系列 3 Ads Management
  • 原文地址:https://www.cnblogs.com/AlphaWA/p/10376573.html
Copyright © 2011-2022 走看看