Codeforces Round #820 (Div. 3) E. Guess the Cycle Size

 

 翻译:

这是一个互动的问题。

我想和你玩个游戏……

我们向您隐藏了一个𝑛顶点的循环图(3≤𝑛≤1018)。循环图是由𝑛个顶点组成的无向图,这些顶点构成一个循环。每个顶点都属于循环,即循环的长度(其中边的数量)正好是𝑛。循环中顶点的顺序是任意的。

您可以通过以下方式进行查询:

”?其中1≤𝑎,𝑏≤1018,𝑎≠𝑏。作为对查询的响应,交互器在单独的一行上输出从顶点𝑎到顶点𝑏的两条路径的随机长度,如果max(𝑎,𝑏)>𝑛则输出-1。交互者以相等的概率选择两条路径中的一条。路径的长度-是其中边的数量。
如果您通过不超过50次的查询猜出隐藏图(数字𝑛)中的顶点数量,则获胜。

注意,交互器的实现方式是,对于任何有序对(𝑎,𝑏),它总是返回相同的查询值"?A b”,不管有多少这样的查询。注意“?”交互者可能会以不同的方式回答查询。

图中的顶点是随机放置的,它们的位置是预先固定的。

在这个问题中禁止黑客攻击。陪审团要进行50次测试

交互
您可以进行不超过50个查询。要进行查询,在单独的一行上输出:

”?其中1≤𝑎,𝑏≤1018,𝑎≠𝑏。作为对查询的响应,交互器将在单独的一行上输出一个从顶点𝑎到顶点𝑏的随机简单路径的长度(不要与从𝑏到𝑎的路径混淆),或者−1如果max(𝑎,𝑏)>𝑛。交互者以相等的概率选择两条路径中的一条。
如果程序的查询结果是0,这意味着您的解决方案的结果已经定义为“错误答案”(例如,您进行了50多个查询或进行了无效查询)。在这种情况下,您的程序应该立即终止。否则,在这种情况下,你可能会得到一个随机的判决“执行错误”,“超时”或其他一些判决,而不是“错误答案”。

答案和查询一样,打印在单独的一行上。在计算它们时,不将答案的输出计算为查询。要打印它,请使用以下格式:

”!N”:隐藏图的期望大小(3≤𝑛≤1018)。
在此之后,您的程序应该终止。

在下一个查询的输出之后,一定要使用流清理函数,这样您的一些输出就不会留在某个缓冲区中。例如,在c++中,你应该使用函数flush(stdout),在Java中调用System.out.flush(),在Pascal中调用flush(output),在Python中使用stdout.flush()。

注意,交互器的实现方式是,对于任何有序对(𝑎,𝑏),它总是返回相同的查询值"?A b”,不管有多少这样的查询。注意“?”交互者可能会以不同的方式回答查询。

图中的顶点是随机放置的,它们的位置是预先固定的。

在这个问题中禁止黑客攻击。陪审团要进行50次测试

例子
inputCopy

1

2

-1
outputCopy
? 1 2

? 1 3

? 1 - 4

! 3.
请注意
在第一个例子中,图形看起来像这样


在这种情况下,所有顶点对之间的简单路径的长度为1或2。

第一个查询发现从顶点1到顶点2的一条简单路径的长度为1。
在第二个查询中,我们发现从顶点1到顶点3的一条简单路径的长度为2。
在第三个查询中,我们发现顶点4不在图中。因此,图的大小为3。

思路:因为每次提问如果不存在则返回-1,并且如果询问1 3,如果n>=3,则会随机选择一条边的长度来回答,但是固定,再去问 3 1,那么如果回答不是一样的,则可以得出来 答案是两次回答加到一起,因为是一个环,这个结论可以画图验证。

代码实现:

#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include <stdio.h>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<tuple>
#include<numeric>
using namespace::std;
typedef long long  ll;
//inline __int128 read(){
//    __int128 x = 0, f = 1;
//    char ch = getchar();
//    while(ch < '0' || ch > '9'){
//        if(ch == '-')
//            f = -1;
//        ch = getchar();
//    }
//    while(ch >= '0' && ch <= '9'){
//        x = x * 10 + ch - '0';
//        ch = getchar();
//    }
//    return x * f;
//}
//inline void print(__int128 x){
//    if(x < 0){
//        putchar('-');
//        x = -x;
//    }
//    if(x > 9)
//        print(x / 10);
//    putchar(x % 10 + '0');
//}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(); cout.tie();
    ll an=0,bn=0;
    for (ll i = 2; ; i++) {
        printf("? 1 %lld\n",i);
        fflush(stdout);
        cin>>an;
        if (an==-1) {
            printf("! %lld\n",i-1);
            fflush(stdout);
            break;
        }
        printf("? %lld 1\n",i);
        fflush(stdout);
        cin>>bn;
        if (an!=bn) {
            printf("! %lld\n",an+bn);
            fflush(stdout);
            break;
        }
        
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值