首页 > 其他分享 >CodeForces 1762D GCD Queries

CodeForces 1762D GCD Queries

时间:2023-01-31 16:23:17浏览次数:47  
标签:zyf return GCD int text CodeForces cin Queries gcd

Preface

比较神仙的交互题,居然自己胡出来了。

不是很建议拿到题直接往题解区冲,这种题做一道少一道。

Solution

下面简称 \(\gcd(p_i,p_j)\) 为 \(\text{zyf}(i,j)\)。

这个限制看起来就像每两步询问就可以检验一个数是否为 \(0\),或者直接判断其不为 \(0\)。但是直接下手有些困难,我们显然需要找到一些性质。

考虑到对于一个排列中元素都不相同,根据这个性质,如果 \(p_i=0\),那么一定满足 \(\text{zyf}(i,j)\not =\text{zyf}(i,k)\),反过来 \(p_i\not =0\) 的充分条件是 \(\text{zyf}(i,j) = \text{zyf}(i,k)\)。

这一条看起来很有用,但是过于狭隘,不一定存在 \(\text{zyf}(i,j)=\text{zyf}(i,k)\),而这又不是必要条件。考虑到这种情况已经需要询问 \(2\) 次,我们不妨继续在 \(\text{zyf}(i,j)\) 和 \(\text{zyf}(i,k)\) 的大小关系上做文章。

于是考虑 \(\text{zyf}(i,j)\not =\text{zyf}(i,k)\),此时发现没法判定 \(p_i\),但是当 \(p_i=0\) 的时候肯定 \(j,k\) 都不为 \(0\),如果 \(p_i \not = 0\) 的时候就说明 \(\text{zyf}(i,j)\) 和 \(\text{zyf}(i,k)\) 是 \(p_i\) 的两个不同的因数。

不妨设 \(\text{zyf}(i,j)<\text{zyf}(i,k)\),那么即使最劣情况下 \(\text{zyf}(i,k)=p_i\),无法判定 \(p_k\),也可以判定 \(p_j\),因为 \(\gcd(p_j,p_i)\not= p_i\not=\gcd(p_i,0)\),所以 \(p_j\not=0\)。

在以上观察之后我们发现,任意的询问 \(\text{zyf}(a,b)\) 和 \(\text{zyf}(a,c)\) 都可以对满足 \(x\in\{a,b,c\}\) 的 \(x\) 进行判定其 \(p_x\not=0\)。于是我们发现只需要判定 \(n-2\) 次就一定可以得到可能为 \(0\) 的两个元素。

Implementation

啊啊啊,\(\mathcal O(n)\) 实现这玩意写挂了,所以我写了一个堆。毕竟交互题比较传统题更难调试一些。

#include <bits/stdc++.h>
using namespace std;
int solve();
signed main() { int t; cin >> t; while (t--) solve(); return 0; }
int _gcd(int x, int y) { 
    cout << "? " << x << " " << y << endl;
    int r; cin >> r; return r;
}
int TESTIFY(int i, int j, int k) {
    int A = _gcd(i, k), B = _gcd(j, k);
    if(A == B) return k;
    if(A < B) return i;
    return j;
}
int solve() {
    int n;
    cin >> n;
    if(n == 2) {
        puts("! 1 2"); int x; cin >> x;
        return 0;
    }
    priority_queue<int> q;
    for(int i = 1; i <= n; i++) q.push(i);
    while(q.size() != 2) {
        int x = q.top(); q.pop();
        int y = q.top(); q.pop();
        int z = q.top(); q.pop();
        int w = TESTIFY(x, y, z);
        if(x != w) q.push(x);
        if(y != w) q.push(y);
        if(z != w) q.push(z);
    }
    cout << "! " << q.top() << ' ';
    q.pop();
    cout << q.top() << endl;
    int x; cin >> x;
    if(x == -1) return puts("WA");
    //This line will be never executed.
    return 0;
}

时间复杂度 \(\mathcal O(n\log n)\)。

标签:zyf,return,GCD,int,text,CodeForces,cin,Queries,gcd
From: https://www.cnblogs.com/eason-hua/p/17079559.html

相关文章

  • Codeforces Round #847 (Div. 3) E. Vlad and a Pair of Numbers(位运算)
    https://codeforces.com/contest/1790/problem/E题目大意:两个正数a和b(a,b>0)。a⊕b=(a+b)/2,a⊕b==x。找到任何合适的a和b,或者不存在"-1"。inputCopy62510......
  • Codeforces Round #846 (Div. 2) 解题报告
    前情提要:我是沙币比赛链接A.Hayatoand贪心,不大想讲代码写的很丑voidsolve(){ vector<int>a; intn,x; cin>>n; a.push_back(0); for(inti=1;i<=n;++i)......
  • Codeforces Global Round 2
    A  题解:枚举每个颜色的头和尾然后最大化另一端upd:赛时麻烦了,显然答案的一端为头或者尾,枚举另一端即可。#include<bits/stdc++.h>usingnamespacestd;typed......
  • 1.30 vp Codeforces Round #846 (Div. 2)
    A-HayatoandSchool、题意给出长度为n的序列a,要求判断是否存在三个数之和为奇数,若有则输出YES且输出这三个数的下标,否则输出NO思路数字和为奇数的情况只有奇+偶,......
  • CF1787H Codeforces Scoreboard 题解
    鬼知道怎么会撞题的,甚至是没听过的OJ。首先不考虑对\(a_i\)取\(\max\),显然直接按照\(k\)降序排序最优。接下来考虑\(a_i\)的限制,如果取到了\(a_i\)一定放在最......
  • Exgcd(扩展欧几里得算法)
    其实挺简单。GCD(辗转相除法)定理:\[\gcd(a,b)=\gcd(b,a\%b)\]证明:\[\text{设}a=kb+r\text{,则}r=a\bmodb\]\[\text{若}c\text{是}a,b\te......
  • 1.29 vp Educational Codeforces Round 142 (Rated for Div. 2)
    A-GamingForces题意有n只怪兽,每个怪的血量是\(a_i\),有两种操作:1.直接消灭这只怪2.消灭两只血量为1的怪问最少需要多少次操作可以将怪全部杀死思路可以想到,操作二......
  • Codeforces Round #844 (Div. 1 + Div. 2, based on VK Cup 2022 - Elimination Roun
    CodeforcesRound#844(Div.1+Div.2,basedonVKCup2022-EliminationRound)[A-D]AParallelProjectionstandardinput/output1s,512MBBGoingt......
  • Codeforces Round #846 (Div. 2) B. GCD Partition
    B.GCDPartition参考题解链接:CodeforcesRound#846(Div.2)—Tutorial-Codeforces题意:给一个长度为n的序列,并将其分成连续的k块(k>1),得到序列......
  • Codeforces Round #847 (Div. 3)
    A.PolycarpandtheDayofPi先纯一下圆周率前30位,然后暴力就好了#include<bits/stdc++.h>usingstd::cin;usingstd::cout;usingstd::string;intread(){...}......