Loading

Team Weekly Contest 2022-10-30

2021 Summer Petrozavodsk Camp, Day 3: IQ test (XXII Open Cup, Grand Prix of IMO)

E. Eulerian?

参考题解

先问出总边数,然后随机一个点集 (A),问这个点集的边数,以及剩下点组成集合 (B) 的边数,总边数减去这两个边数之和即为 (A) 和 (B) 之间的边数。

如果有一次 (A) 和 (B) 之间的边数是奇数,说明没有欧拉回路,否则有。

#include <bits/stdc++.h>

using namespace std;
#define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
#define rep(a, b, c) for(int (a)=(b);(a)<=(c);(a)++)
#define ll long long
#define int ll
#define fi first
#define se second
#define no "! NO"<<endl
#define yes "! YES"<<endl
#define pii pair<int,int>

const int N = 2e5 + 5;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;

int a[N];
int n,all;
map<int,int>mp;

void update(){
    mp[1]=rand() %2;
    mp[2]=mp[1]^1;
    rep(i,3,n){
        mp[i]=rand() %2;
    }
}

bool check(){
    int x,y,sum1=0;
    rep(i,1,n){
        if(mp[i]==1){
            sum1++;
        }
    }
    cout<<"? "<<sum1<<" ";
    rep(i,1,n){
        if(mp[i]==1){
            cout<<i<<" ";
        }
    }
    cout<<endl;
    cin>>x;

    cout<<"? "<<n-sum1<<" ";
    rep(i,1,n){
        if(mp[i]==0){
            cout<<i<<" ";
        }
    }
    cout<<endl;
    cin>>y;

    if(abs(all-x-y)%2==0)   return true;
    return false;
}

void  solve(){
    cin >> n;
    update();
    cout<<"? "<<n<<" ";
    rep(i,1,n){
        cout<<i<<" ";
    }
    cout<<endl;
    cin>>all;
    for(int i=1;i<=28;i++){
        if(!check()){
            cout<<no;
            return;
        }
        update();
    }
    cout<<yes;
}

signed main() {
    IOS;
    int t = 1;
//    cin >> t;
    while (t--) {
        solve();
    }
    return 0;
}
posted @ 2022-11-02 20:30  ShG1211  阅读(71)  评论(0)    收藏  举报