AtCoder Beginner Contest 313

AtCoder Beginner Contest 313 - AtCoder

A - To Be Saikyo (atcoder.jp)

\(a_1 \dots a_{n-1}\)找出最大值与\(a_0\)比较即可

#include <bits/stdc++.h>
#define int long long
#define endl '\n'

using namespace std;

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n;
    cin >> n;
    vector<int> A(n);
    for(auto &i : A) cin >> i;

    int ma = *max_element(A.begin() + 1, A.end());
    cout << max(ma - A[0] + 1, 0ll) << endl;

    return 0;
}

B - Who is Saikyo? (atcoder.jp)

每次将能力更弱的去掉,看最后是否还剩一个最强的

#include <bits/stdc++.h>
#define int long long
#define endl '\n'

using namespace std;

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int N,M;
    cin >> N >> M;

    set<int> A;
    for(int i = 1;i <= N;i ++)
        A.insert(i);

    for(int i = 0;i < M;i ++){
        int x,y;
        cin >> x >> y;
        A.erase(y);
    }

    if(A.size() == 1)
        cout << *A.begin() << endl;
    else
        cout << "-1\n";

    return 0;
}

C - Approximate Equalization 2 (atcoder.jp)

因为可以用大的去补小的,所以都往中间靠,要计算小于平均数的差多少到平均数,将这些分配好后,如果还有还有大于平均数+1的,还要继续分配,\(sum\bmod n\)就是计算多出来的,另外那些本身大于平均数的数只要减到比平均数多1即可,不用完全减到和平均数相等

#include <bits/stdc++.h>
#define int long long
#define endl '\n'

using namespace std;

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int N;
    cin >> N;
    vector<int> A(N + 1);
    int sum = 0;
    for(int i = 1;i <= N;i ++){
        cin >> A[i];
        sum += A[i];
    }

    int ans = 0,num = 0, tag = sum / N;
    for(int i = 1;i <= N;i ++){
        ans += max(tag - A[i], 0ll);
        num += (A[i] > tag);
    }

    cout << ans + max(sum % N - num,0ll) << endl;
    return 0;
}

D - Odd or Even (atcoder.jp)(交互题)

因为原数组仅由\(0,1\)构成,并且每次询问后\(a_1 + a_2 + \dots +a_k\)的和的奇偶性也是用\(01\)表示,所以我们可以把和当作$a_1 \oplus a_2 \oplus \dots \oplus a_k $的值.

\(n=4,k=3\)时,我们可以询问1 2 3 ,1 2 4, 1 3 4 ,将三个结果的值异或之后就是\(a_1\)的值.

三个结果异或即:

\(res_1 \oplus res_2 \oplus res_3 = a_1 \oplus a_2 \oplus a_3 \oplus a_1 \oplus a_2 \oplus a_4 \oplus a_1 \oplus a_3 \oplus a_4\)

根据异或的性质,一个数异或自身偶数次等于\(0\),而0异或其他数等于其他数,所以上式的值就等于\(a_1\).

同理,如果再询问2 3 4,结合1 2 3,1 2 4,我们可以得到\(a_2\)的值.

由此我们对前\(k+1\)个数进行询问就能得到前\(k+1\)个数的值,那怎么得到\(k+2\)之后的值呢?

我们可以询问\(3,4 \dots k+1,k+2\)的结果,即\(a_3 \oplus a_4 \dots a_{k+1} \oplus a_{k+2}\)的值,且前面\(a_3 \sim a_{k+1}\)我们都已经知道了,那把前面这个\(res\)去异或上它们不就得到\(a_{k+2}\)的值了吗.

#include <bits/stdc++.h>

using namespace std;

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int N, K;
	cin >> N >> K;
	vector<int> ans(N);

	auto solve = [&]() {
		vector<int> T(K + 1);
		vector<int> Q;
		for (int i = 0; i <= K; i ++) {
			Q.clear();
			for (int j = 0; j <= K; j ++)
				if (j != i)
					Q.emplace_back(j);

			cout << '?';
			for (auto j : Q)
				cout << ' ' << j + 1 ;
			cout << endl;

			cin >> T[i];
		}

		for (int i = 0; i <= K; i ++)
			for (int j = 0; j <= K; j ++)
				if (j != i)
					ans[i] ^= T[j];
	};

	solve();

	for (int i = K + 1; i < N; i ++) {
		cout << '?';
		for (int j = i; j > i - K; j--)
			cout << ' ' << j + 1;
		cout << endl;

		cin >> ans[i];
		for (int j = i - 1; j > i - K; j --)
			ans[i] ^= ans[j];
	}

	cout << '!';
	for (auto i : ans)
		cout << ' ' << i;
	cout << endl;

	return 0;
}
posted @ 2023-08-07 18:55  Ke_scholar  阅读(39)  评论(0编辑  收藏  举报