Codeforces Round #482 (Div. 2) 题解(ABC)

A题

题意:给你一个整数n,询问你在一个圆形蛋糕中需要切几刀才能分成(n-1)块相等的蛋糕。

思路:
注意:输入的n是有几个人,切成的蛋糕是要n+1的,因为本人也要一块蛋糕,还有就是要特判0这种情况。
大概这就是结论题,如果需要切成偶数块蛋糕,那么需要n/2,如果是奇数,那么需要n刀。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n;
int main() {
    scanf("%I64d", &n);
if(n==0) printf("0\n");
else if(n&1) printf("%I64d\n",(n+1)/2);
 else printf("%I64d\n",n+1);
    return 0;
}

B题

题意:给一个整数n代表变换(变换是指将一个字母变成另一个字母)的次数,再给三个一样长度的字符串,问你每个字符串经过n次变换后,字符串的重复字母最多的是哪个。
注意:每个字符串必须要经过n次变换,且不能是a变换成a这种情况。
思路:贪心模拟题目意思即可。只要记录每个字符串中重复的次数最多的即可。然后这个次数+n>字符串长度,那么最后结果就是字符串的长度。
需要注意的是n==1&&字符串是同一字母的这种情况,这个的结果是字符串长度-1.

给一个样例:

4
aaaa
aabb
aaab

解释
aaaa-aaac-aaaa-aaac-aaaa
aabb-aabc-aabd-aaad-aaaa
aaab-aaac-aaad-aaac-aaaa

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 5;
int n;
int len[4], MAX[4];
map<char, int>mp[4];
char a[4][maxn];
int main() {
    scanf("%d", &n);
    for(int i = 1; i <= 3; i++) {
        scanf("%s", a[i]);
    }
    len[1] = len[2] = len[3] = strlen(a[1]);

    if(n > len[1]) printf("Draw\n");
    else {
        for(int i = 1; i <= 3; i++) {
            for(int j = 0; j < len[i]; j++) {
                mp[i][a[i][j]]++;
                MAX[i] = max(MAX[i], mp[i][a[i][j]]);
            }
        }
        for(int i = 1; i <= 3; i++) {
            if(MAX[i] == len[1] && n ==1) {
                MAX[i]--;
                continue;
            }
                MAX[i] = min(len[1], MAX[i] + n);
        }

        int win = 1;
        int sum = MAX[1];
        for(int i = 2; i <= 3; i++) {
            if(MAX[i] > sum) {
                win = i;
                sum = MAX[i];
            }
        }

        for(int i = 1; i <= 3; i++) {
            if(MAX[i] == sum && win != i) win = -1;

        }
        if(win == -1) printf("Draw\n");
        else if(win == 1) printf("Kuro\n");
        else if(win == 2) printf("Shiro\n");
        else if(win == 3) printf("Katie\n");
    }
    return 0;
}

C题

题意:给你n个城市,给出n-1条边,题目保证n个城市连成一棵树。然后有给出一对特别的城市x,y,你不能在经过了x之后再经过y城市,询问你有多少种走法。

思路:我们可以发现如果不计算x,y城市,我们一共可以有n(n-1)种走法。所以,这时候 我们只需要减去不满足的路径即可。我们可以知道不满足的路径数量ret1*ret2.
ans=n*(n -1)-ret1*ret2
ret1=以x为根节点的整棵树的结点数(不向y节点的方向搜索)
ret2=以y为根节点的整棵树的结点数(不向x节点的方向搜索)

下面是我写的代码,有点丑陋,不够简洁

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n, x, y;
const int maxn = 3e5 + 5;
vector<int>G[maxn];
vector<int>path;
vector<int>::iterator it;
stack<int>s;
int flag = 0;
int fx, fy, ret1, ret2;
void dfs(int x, int fa) {//搜索从x到y的路径,并做标记。目的的记录x和y节点的父节点
    if(x == y) {
        flag = 1;
        s.push(x);
        return;
    }
    for(int i = 0; i < G[x].size(); i++) {
        int v = G[x][i];
        if(fa != v)dfs(v, x);
        if(flag) {
            if(s.size() == 1) fy = x;
            s.push(x);
            return;
        }
    }
}
void dfs1(int yuan,int t, int fa) {//搜索ret1和ret2的值
    for(int i = 0; i < G[t].size(); i++) {
        int v = G[t][i];
        if(fa != v) {
           if(yuan==x) ret1++;
           else if(yuan==y) ret2++;
            dfs1(yuan,v, t);
        }
    }
}
int main() {
    scanf("%d%d%d", &n, &x, &y);
    for(int i = 1; i <= n - 1; i++) {
        int u, v;
        scanf("%d%d", &u, &v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    dfs(x, -1);
    while(!s.empty()) {
        path.push_back(s.top());
        s.pop();
    }
    fx = path[1];
    ret1=1;
    ret2=1;
    dfs1(x,x, fx);
    dfs1(y,y, fy);
    printf("%I64d\n",1LL* n * (n - 1) - 1LL*ret1 * ret2);//记得两边都要加1LL,我就是只加了一边,找了3小时bug
    return 0;
}

下面是大佬的代码,简洁多了,主要是只用了一遍dfs,用来par数组来标记每一个节点的父节点,用num[u]表示以u节点为根节点的整棵树的节点数。
只是要注意一点:给出的x和y不一定是直接相连的,所以有了这个语句

  int m = y;
 while (par[m] != x)
    {
        m = par[m];
    }
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 3e5 + 10;
vector<int> g[N];
int num[N];
int par[N];
int n,x,y;
int dfs(int u,int fa)
{
    par[u] = fa;
    int cnt = 0;
    for (int v:g[u])
    {
        if (v != fa)
        {
            cnt += dfs(v,u);
        }
    }
    return num[u] = cnt + 1;
}
int main()
{
    scanf("%d%d%d",&n,&x,&y);
    for (int i = 1;i < n;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        g[u].push_back(v);
        g[v].push_back(u);
    }
    dfs(x,-1);
    long long ans = 0;
    int m = y;
    while (par[m] != x)
    {
        m = par[m];
    }

    ans = (long long) n * (n - 1);
    ans -= (long long)num[y] * (1LL * (n - num[m]));
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yiqzq/article/details/80321392