Featured image of post 2100

2100

GCD Queries

出处:CF1762D

题目大意:交互题,给定一个秘密的 $[0,n-1]$ 排列 $p$ ,请在至多 $2n$ 次询问下,找出 $p_x$ 和 $p_y$ 其中,至少有一个位置为 $0$ ,每次询问给出 $i,j$ ,返回 $gcd(i,j)$ 。

数据范围: $2 \leq n \leq 2 \cdot 10^4$ 。

思路:这道题其实跟CF1634D 非常相似,思路都是动态更新当前可能的解。

于是,这里考虑每次判断三个数,要排除掉一个必然不是0的数,于是如何排除?

考虑当前的数为 $a,b,c$ ,查询 $gcd(a,b)$ 和 $gcd(a,c)$ 。

若 $gcd(a,b)=gcd(a,c)$ ,那么 $a$ 必然不是 $0$ 。

若 $gcd(a,b)>gcd(a,c)$ ,那么 $c$ 必然不是 $0$ ,可以使用反证法证明。

若 $gcd(a,b)<gcd(a,c)$ ,那么 $b$ 必然不是 $0$ ,可以使用反证法证明。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
int ask(int l, int r) {
    cout << "? " << l << ' ' << r << '\n';
    cout.flush();
    int op;
    cin >> op;
    return op;
}
void report(ll sum, ll sum2) {
    cout << "! " << sum << ' ' << sum2 << '\n';
    cout.flush();
    int op;
    cin >> op;
    if (op == 1)
        return;
    else
        exit(0);
}
void solve() {
    int n;
    cin >> n;
    pii ans = make_pair(1, 2);
    auto upd = [&](int x) -> void {
        int op1 = ask(ans.first, x);
        int op2 = ask(ans.second, x);
        if (op1 == op2)
            ans = make_pair(ans.first, ans.second);
        else if (op1 > op2)
            ans = make_pair(ans.first, x);
        else
            ans = make_pair(ans.second, x);
    };
    rep(i, 3, n) { upd(i); }
    report(ans.first, ans.second);
    return;
}
本博客已稳定运行
发表了54篇文章 · 总计349.50k字
使用 Hugo 构建
主题 StackJimmy 设计