Codeforces Round 774 div.2 DEF

本文最后更新于:2 年前

D. Weight the Tree

题意:给定一棵树,每个节点有一权重 $w_i$,若一个节点的权值等于其相邻点的权值之和,则这个节点是好的。现在你可以为每个,使得好的点数量最多,在这基础上,还要使得总权值最小,输出赋值方案。

首先想到,除了 $n=2$ 的情况,相邻两个点不可能都是好的

对于不好的点,肯定让它为1($w_i\ge1$),那么好的点的权值一定等于其度数,我们要选上一些不相邻的点使得它

考虑树上dp,$dp[i,0/1]$ 表示以 $i$ 为根节点的子树,选/不选根节点时的最优解。这里比较难想的一点在于,解居然包括了两个信息:好节点数量和总权值。似乎和通常的dp不太一样,但仔细想想是没问题的,因为两个解仍然可以排序:先按照好节点数,再按照总权值。

当前节点选,则其子节点都不能选,当前节点不选,则其子节点任意。

最后要输出方案,从上往下跑一遍就可以了:每个节点的 $dp[i,1]$ 和 $dp[i, 0]$ 比较一下,确定当前点是否选,如果其父节点选了,则强制这个点不选,这样往下搜下去就能确定方案了,

int n, du[maxn];
vector<int> vp[maxn];
int f[maxn][2], g[maxn][2];

bool chose(int x){
    if(f[x][1] == f[x][0]) return g[x][1] < g[x][0];
    return f[x][1] > f[x][0];
}

void dfs(int p, int fa = -1){
    f[p][0] = 0, f[p][1] = 1;
    g[p][0] = 1, g[p][1] = du[p];
    for(int v: vp[p]){
        if(v != fa){
            dfs(v, p);
            f[p][1] += f[v][0];
            g[p][1] += g[v][0];
            int cs = chose(v);
            f[p][0] += f[v][cs];
            g[p][0] += g[v][cs];
        }
    }
}

int ans[maxn];
void getans(int p, int fa, int cs){
    ans[p] = cs ? du[p] : 1;
    for(int v: vp[p]){
        if(v != fa){
            if(cs) getans(v, p, 0);
            else getans(v, p, chose(v));
        }
    }
}

void solve(){
    cin >> n;
    if(n == 2){
        cout << "2 2\n1 1\n";
        return;
    }
    for(int i=1;i<n;i++){
        int x, y;
        cin >> x >> y;
        du[x]++, du[y]++;
        vp[x].emplace_back(y);
        vp[y].emplace_back(x);
    }
    dfs(1);
    int cs = chose(1);
    getans(1, -1, cs);
    cout << f[1][cs] << ' ' << g[1][cs] << '\n';
    for(int i=1;i<=n;i++) cout << ans[i] << " \n"[i == n];
}

E. Power Board

题意:给出一个 $n\times m$ 的图,$(i,j)$ 点上的数字为 $i^j$ ,请问这个图里有多少个不同的数字?

没法比题解写的更清楚了(摆

int n, m;
bool vis[maxn << 5];
int cnt[32];
void solve(){
    cin >> n >> m;
    int tot = 0;
    for(int i=1;i<=23;i++){
        for(int j=1;j<=m;j++){
            if(!vis[i * j]){
                vis[i * j] = true;
                tot++;
            }
        }
        cnt[i] = tot;
    }
    fill(vis, vis+n+1, false);
    ll ans = 1;
    for(int i=2;i<=n;i++){
        if(!vis[i]){
            int k = 0;
            for(ll j=i;j<=n;j*=i){
                vis[j] = true;
                k++;
            }
            ans += cnt[k];
        }
    }
    cout << ans << '\n';
}

F. Playing Around the Table

题意:有 $n$ 名玩家坐成一个环,一共有 $n^2$ 张卡牌,$1-n$ 每种卡牌各 $n$ 张,开局每名玩家持有其中 $n$ 张,接下来进行游戏:每轮中,每名玩家交给下一名玩家一张卡牌(所有人同时进行),如果玩家 $i$ 的所有卡牌都为 $i$,则其“牢固”。现要你构造一种游戏方案,至多 $n^2-n$ 轮,使得每名玩家都“牢固”。

一开始有个暴力的想法,每轮每个人都直接找一个不属于自己的卡牌传出去,然而这样显然会遇到死循环的情况。

全变成一样的不好搞,能不能先全变成不一样的呢?也就是让每个人都拥有1到n的所有卡牌。

这个比较好搞,每次每人都找一张自己有重复的卡牌交出去,如果自己没有重复的,就把上一个人传过来的交出去,这样最终一定能满足。

第一步能在可接受的步数内完成吗?对于每一种卡牌,考虑其最坏的情况:初始所有这张牌都在一个人手上,那么根据上述传递方案,这张牌一共会被传递 $1+2+…+n-1$ 次,即 $\frac{n\times(n-1)}{2}$ 次,那么一共 $n$ 张牌,一轮能传递 $n$ 次,总轮次不会超过 $\frac{n\times(n-1)}{2}$。

现在所有人的牌都是 $1..n$ 了,下一步怎么搞都行

int n;
int cnt[103][103];
void solve(){
    cin >> n;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            int x; cin >> x;
            cnt[i][x]++;
        }
    }
    vector<int> pass(n+1, 0);
    vector<vector<int>> ans;
    while(true){
        for(int i=1;i<=n;i++){
            pass[i] = 0;
            for(int j=1;j<=n;j++){
                if(cnt[i][j] > 1){
                    pass[i] = j;
                    break;
                }
            }
        }
        for(int i=1;i<=n;i++) if(pass[i] == 0) pass[i] = pass[(i-1+n-1)%n+1];
        for(int i=1;i<=n;i++) if(pass[i] == 0) pass[i] = pass[(i-1+n-1)%n+1];
        if(pass[1] == 0) break;
        for(int i=1;i<=n;i++){
            cnt[i][pass[i]]--;
            cnt[i%n+1][pass[i]]++;
        }
        ans.push_back(pass);
    }

    for(int k=1;k<n;k++){
        for(int d=k;d>=1;d--){
            for(int i=1;i<=n;i++){
                pass[i] = (i + d - 1) % n + 1;
            }
            ans.push_back(pass);
        }
    }
    cout << ans.size() << '\n';
    for(auto ps: ans){
        for(int i=1;i<ps.size();i++) cout << ps[i] << " \n"[i == ps.size()-1];
    }
}

Codeforces Round 774 div.2 DEF
http://www.lxtyin.ac.cn/2022/03/05/2022-03-05-Codeforces Round 774 div.2 DEF/
作者
lx_tyin
发布于
2022年3月5日
许可协议