Codeforces Round #770(Div.2) [A~D]

链接:contest link

A.Reverse and Concatenate

题目

给定一个长度为 \(n\) 的字符串 \(s\) 和一个整数 \(n\) ,用 \(rev(s)\) 表示将字符串 \(s\) 反转,你可以对 \(s\) 执行 \(k\) 次如下操作:

  • \(s\) 变为 \(s+rev(s)\)
  • \(s\) 变为 \(rev(s)+s\)

求可以得到多少个不同的字符串

分析

如果 \(s\) 是回文串,那么无论执行哪种操作得到的结果都是一样的,所以执行 \(k\) 次操作后得到的不同字符串数为 \(1\)

如果 \(s\) 不是回文串,那么 \(k=0\) 时显然答案为 \(1\)\(k\geq1\) 时,第一次操作可以将产生两个不同的回文串,根据上面对于回文串的讨论,答案为 \(2\)

代码

#include<bits/stdc++.h>
using namespace std;

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    int t;
    cin >> t;
    while(t--) {
        int n, k;
        cin >> n >> k;
        string s;
        cin >> s;
        if(k == 0) {
            cout << 1 << endl;
            continue;
        }
        s = ' ' + s;
        bool flag = true;
        for(int i = 1; i <= n / 2; i++) {
            if(s[i] != s[n + 1 - i]) {
                flag = false;
                break;
            }
        }
        cout << (flag ? 1 : 2) << endl;
    }
    return 0;
}

B.Fortune Telling

题目

给定一个长度为 \(n\) 的数组 \(a\) 和整数 \(x,y\) ,判断 \(x\)\(x+3\) 进行 \(n\) 次如下操作后能否变为 \(y\) ,第 \(i\) 次操作可以在下面两条中任选一条执行:

  • 将当前数字 \(d\) 替换为 \(d+a_i\)
  • 将当前数字 \(d\) 替换为 \(d\oplus a_i\)

保证 \(x\)\(x+3\) 中一定有一个能用适当操作变为 \(y\)

分析

  • \(d\) 为偶数
    • \(a_i\) 为偶数,无论执行哪种操作 \(d\) 奇偶性都不变
    • \(a_i\) 为奇数,无论执行哪种操作 \(d\) 都会变为奇数
  • \(d\) 为奇数
    • \(a_i\) 为偶数,无论执行哪种操作 \(d\) 奇偶性都不变
    • \(a_i\) 为奇数,无论执行哪种操作 \(d\) 都会变为偶数

所以每一种操作对于奇偶性的改变是相同的,那么判断遍历数组执行操作后 \(x,y\) 奇偶性是否相同即可,若不相同则 \(x\) 无论如何都不能变为 \(y\) ,那 \(x+3\) 一定可以

代码

#include<bits/stdc++.h>
using namespace std;

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    int t;
    cin >> t;
    while(t--) {
        long long n, x, y, a;
        cin >> n >> x >> y;
        for(int i = 1; i <= n; i++) {
            cin >> a;
            if(x % 2 && a % 2) {
                x++;
            } else if(x % 2 == 0 && a % 2) {
                x++;
            }
        }
        cout << (x % 2 == y % 2 ? "Alice" : "Bob") << endl;
    }
    return 0;
}

C.OKEA

题目

给定 \(n,k\) 构造一个 \(n\times k\) 的矩阵 \(a\) ,满足:

  • \(1\)\(n\cdot k\) 的每个整数都出现在矩阵上且仅出现一次
  • 对于任意 \(i,l,r\) 满足 \(a_{i,l},a_{i,l+1},\cdots,a_{i,r}\) 的算术平均值是整数

分析

可以发现任意一行内的奇偶性是相同的,如果一行内既存在奇数又存在偶数,那么一定存在一个奇偶相邻的情况,它们的算术平均值不是整数

若每行的奇偶性都相同,那么可以构造:

\[\left[\begin{array}{ccc} 1 & 3 & \cdots &2k-1\\ 2 & 4 & \cdots & 2k\\2k+1 & 2k+3 & \cdots & 4k-1\\ \vdots & \vdots & \vdots &\vdots\end{array}\right] \]

对任意一段 \(i,l,r\) 进行求和,可以用等差数列求和公式,可以发现和一定是 \(l+r-1\) 的倍数,那么算术平均值也一定是整数。进一步,可以求出通项公式 \(a_{i,j}=2(j+k\lfloor\frac{i-1}{2}\rfloor)-i\bmod 2\)

代码

#include<bits/stdc++.h>
using namespace std;

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    int t;
    cin >> t;
    while(t--) {
        int n, k;
        cin >> n >> k;
        if((n % 2 && k == 1) || n % 2 == 0) {
            cout << "YES" << endl;
            for(int i = 1; i <= n; i++) {
                for(int j = 1; j <= k; j++)
                    cout << 2 * ((i - 1) / 2 * k + j) - i % 2 << ' ';
                cout << endl;
            }
        } else {
            cout << "NO" << endl;
        }
    }
    return 0;
}

D.Finding Zero

题目

题意较复杂,参考原文 Problem D

分析

考虑一个长度为 \(4\) 的序列 \(a,b,c,d\) ,不妨设 \(a\leq b\leq c\leq d\) ,设 \(\overline{a}=\max(b,c,d)-\min(b,c,d)\) ,进行四次询问可得:

\[\overline{a}=d-b\\ \overline{b}=d-a\\ \overline{c}=d-a\\ \overline{d}=c-a \]

易知 \(\overline{b},\overline{c}\) 是四次询问中结果最大的且 \(c\geq b\geq a\) ,序列中的所有数中只有一个 \(0\) 且其他数都大于 \(0\) ,所以对于任意一个长度为 \(4\) 的序列,询问结果最大的两个数一定不是 \(0\) ,那么我们每次处理长度为 \(4\) 的序列,排除掉不可能为 \(0\) 的两个不可能为 \(0\) 的选项,再继续加入两个数,以此类推

这样当给定长度 \(n\) 为偶数时,要执行 \(\frac{(n-4)}{2}\times 4+4=2n-4\) 次询问,\(n\) 为奇数时最后会剩下一个长度为 \(3\) 的序列,我们把之前已经排除的某个选项再次加入,使序列长度变为 \(4\) ,要执行 \(\frac{n-1-4}{2}\times4+2\times 4=2n-2\) 次询问,满足要求

代码

#include<bits/stdc++.h>
using namespace std;

int n;
int del;

int query(int a, int b, int c)
{
    cout << "? " << a << ' ' << b << ' ' << c << endl;
    int res;
    cin >> res;
    return res;
}

vector<int> cal(vector<int> v) 
{
    vector<pair<int, int> > t;
    t.push_back({query(v[1], v[2], v[3]), v[0]});
    t.push_back({query(v[0], v[2], v[3]), v[1]});
    t.push_back({query(v[0], v[1], v[3]), v[2]});
    t.push_back({query(v[0], v[1], v[2]), v[3]});
    sort(t.begin(), t.end());
    del = t.back().second;
    return {t[0].second, t[1].second};
}

void solve() 
{
    cin >> n;
    vector<int>v;
    for(int i = 1; i <= n; i++) {
	 v.push_back(i);
	 if(v.size() == 4)
            v = cal(v);
    }
    if(v.size() == 2) { 
        cout <<"! "<< v[0] << ' ' << v[1] << endl; 
    } else {
	v.push_back(del);
	v = cal(v);
	cout<<"! " << v[0] << ' ' << v[1] << endl;
    }
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    int t;
    cin >> t;
    while(t--) {
        solve();
    }
    return 0;
}
posted @ 2022-03-16 11:00  f(k(t))  阅读(23)  评论(0编辑  收藏  举报