完整源代码:https://github.com/abmcar/ACM/tree/master/OpenjudgeNow/Codeforces/Codeforces%20Round%20%23762%20(Div.%203)

A. Square String?

在这里插入图片描述
题目大意:给你一个字符串,让你判断这个字符串是不是由两个相同的字符串组成
思路:截取源字符串的一半,拼接成一个新的字符串,跟源字符串判断是否相同
代码:

void work()
{
    string oriString;
    cin >> oriString;
    string newString = oriString.substr(0, oriString.size() / 2);
    if (newString + newString == oriString)
        cout << "YES" << endl;
    else
        cout << "NO" << endl;
}

B. Squares and Cubes

在这里插入图片描述
题目大意:给你一个在1e9范围内的数,问有多少数小于这个数且是平方数(ii)或者立方数(ii*i)
思路:直接暴力跑i * i和i * i * i,用map判重
代码:

void work()
{
    int n;
    cin >> n;
    M.clear();
    for (int i = 1; i * i <= n; i++)
        M[i * i] = 1;
    for (int i = 1; i * i * i <= n; i++)
        M[i * i * i] = 1;
    cout << M.size() << endl;
}

C. Wrong Addition

在这里插入图片描述
题目大意:这个麻瓜算竖式不会进位,给你s和a,让你求b使得a+b=s在他错误的进位下成立
思路:已知a长度小于s,且根据题意a/b中的一位相加至多是s的2位,我们知道在他的计算下,多出来的s多出来的位数必定是a的某一位和b的某一位相加进位了,直接dfs判断是否进位,p1,p2,nowAns分别表示s当初位,a当前位,当前的b
代码:

int getSNum(int pos)
{
    return (s[pos + 1] - '0') * 10 + s[pos] - '0';
}

void dfs(int p1, int p2, string nowAns)
{
    if (p1 == s.size())
    {
        if (p2 >= a.size())
        b = nowAns;
        // cout << nowAns << endl;
    }
    if (p1 >= s.size())
        return;
    if (p1 < s.size() - 1 && s[p1 + 1] != '0')
    {
        int oriNum = getSNum(p1);
        int nowNum = p2 < a.size() ? a[p2] - '0' : 0;
        if (oriNum - nowNum >= 0 && oriNum - nowNum < 10)
            dfs(p1 + 2, p2 + 1, nowAns + (char)(oriNum - nowNum + '0'));
    }
    int oriNum = s[p1] - '0';
    int nowNum = p2 < a.size() ? a[p2] - '0' : 0;
    if (oriNum - nowNum >= 0 && oriNum - nowNum < 10)
        dfs(p1 + 1, p2 + 1, nowAns + (char)(oriNum - nowNum + '0'));
}

void work()
{
    cin >> a >> s;
    reverse(a.begin(), a.end());
    reverse(s.begin(), s.end());
    b = "-1";
    dfs(0, 0, "");
    reverse(b.begin(), b.end());
    while (b[0] == '0' && b.size() > 0)
        b.erase(0, 1);
    if (b == "1-")
        b = "-1";
    cout << b << endl;
}

D. New Year's Problem

在这里插入图片描述
题目大意:给你一个m*n的数组p,你需要在(n-1)列中找n个不同行的数,使得最小值最大
思路:我们想要找的n个数有2个条件
1.只能在(n-1)列中
2.只能在不同行
分开来看,我们现在思考第一个条件,如果只是这样,可以假设最坏情况,m=n,此时最小值为各列第二大的数中最大的(每列选最大的,有一列选了2个),对于第二个条件,则最小值为每行中最大的数中最小的.
把两个条件结合起来,得到答案--每列次大中最大的和每行最大中较小的
(绕的一b建议好好想一下)
代码:

void work()
{
    ans = 0;
    cin >> m >> n;
    for (int i = 1; i <= n; i++)
        p[i].resize(m + 1), p[i].clear();
    for (int i = 1; i <= m; i++)
        q[i].resize(n + 1), q[i].clear();
    for (int i = 1; i <= m; i++)
        for (int j = 1; j <= n; j++)
        {
            cin >> q[i][j];
            p[j][i] = q[i][j];
        }
    for (int i = 1; i <= m; i++)
        sort(q[i].begin() + 1, q[i].begin() + 1 + n, greater<int>());
    for (int i = 1; i <= n; i++)
        sort(p[i].begin() + 1, p[i].begin() + 1 + m, greater<int>());
    for (int i = 1; i <= m; i++)
    {
        ans = max(ans, q[i][2]);
        // cout << q[i][1] << " ";
    }
    // cout << endl;
    for (int i = 1; i <= n; i++)
        ans = min(ans, p[i][1]);
    cout << ans << endl;
}

E. MEX and Increments

在这里插入图片描述
题目大意:给你一个数组,你可以对任意数+1,问能不能使得MEX = 0,1,2,3,...,n,能则求最小操作数
思路:
得到MEX = i的前提是,数组中存在0-(i-1)且不存在i,分开来看,我们用ans表示组成0-(i-1)的操作数,若存在i,则数组中i的数量即为移开i的操作数,我们可以优先队列表示之前的数,cnt表示构成0-(i-1)的代价,每次求MEX = i,把数组中值等于i的数入队,并用当前剩余的数中最大是数加到i,结束,若不剩余,则不可使得Mex = i
代码:

void work()
{
    cin >> n;
    unordered_map<int, int> M;
    vector<int> V(n + 1);
    for (int i = 1; i <= n; i++)
        cin >> V[i], M[V[i]]++;
    priority_queue<int> Q;
    vector<int> ans(n + 1, -1);
    int cnt = 0;
    for (int i = 0; i <= n; i++)
    {
        ans[i] = cnt + M[i];
        while (M[i]--)
            Q.push(i);
        if (!Q.empty())
        {
            cnt += i - Q.top();
            Q.pop();
        }
        else
            break;
    }
    for (int i = 0; i <= n; i++)
        cout << ans[i] << " ";
}

Q.E.D.