12.17 CW 模拟赛 赛时记录

前言

这一次又来更新比赛策略

讲真打了这么久, 还没有一个好的比赛策略真的是抽象

回去吃点感冒药

看题

怎么 T1 T2 是一个题

T1 可能是 dp

T3 有些不好做

T4 这种题一般都不会做, 能骗多少是多少

T1

思路#

转化题意

对于两组, 一组有 n 个点, 另一组有 m 个点, 求如何从两组中选取点, 使得 w 之和相等的情况下, v 最大

本身就很像 dp , 我们考虑推一下朴素的方程

fi,j 表示考虑到第 i 个人, 此时两个组织间的 w 之差为 j , 最大的精彩度

考虑转移,

fi,j={fi1,jfk,j±wi+vi

其中 ± 由当前选择的位置与 k 是否在同一组而决定


又想了一些杂七杂八的事情, 先放过这个题, 我们看一下 30% 怎么拿
注意以后即使不考试, 也要时间分配好


对于 n,m 很小的情况下, 我们考虑预处理出可能的 w 值对应的最大 v, 这很像一个背包

那么我们将这两个背包组合起来, 就得到了答案

整个的复杂度为 O(n2w)

先打, 时间不足后面再来找高分

实现#

框架#

先做两个背包, 然后枚举合并答案即可

代码#

#include <bits/stdc++.h>
#define int long long
const int MAXN = 120;
const int MAXC = 52064;

int n, m;
struct student {
    int w; // 能力值
    int v; // 精彩度
} stu1[MAXN], stu2[MAXN];

int maxc = 0;
int dp1[MAXC], dp2[MAXC];
/*两边各做一次背包*/
void init()
{
    for (int i = 1; i <= 50000; i++) dp1[i] = dp2[i] = -0x3f3f3f3f;

    int C = 0; for (int i = 1; i <= n; i++) C += stu1[i].w;
    maxc = std::max(maxc, C);
    for (int i = 1; i <= n; i++) {
        for (int j = C; j >= stu1[i].w; j--) {
            dp1[j] = std::max(dp1[j], dp1[j - stu1[i].w] + stu1[i].v);
        }
    }

    C = 0; for (int i = 1; i <= m; i++) C += stu2[i].w;
    maxc = std::min(maxc, C);
    for (int i = 1; i <= m; i++) {
        for (int j = C; j >= stu2[i].w; j--) {
            dp2[j] = std::max(dp2[j], dp2[j - stu2[i].w] + stu2[i].v);
        }
    }
}

signed main()
{
    scanf("%lld %lld", &n, &m);
    for (int i = 1; i <= n; i++)
        scanf("%lld %lld", &stu1[i].w, &stu1[i].v);
    for (int i = 1; i <= m; i++)
        scanf("%lld %lld", &stu2[i].w, &stu2[i].v);

    init();

    int Ans = 0;
    for (int i = 0; i <= maxc; i++) {
        if (dp1[i] != -0x3f3f3f3f && dp2[i] != -0x3f3f3f3f)
            Ans = std::max(Ans, dp1[i] + dp2[i]);
    }

    printf("%lld", Ans);

    return 0;
}

预期得分 : 30pts

T2

思路#

转化题意,

对于一颗树, 我们定义一个花费是指从 m 个互不相同的点到一个点, 路径长度之和的最小值
求出对于任意一种 m 节点的位置, 花费的总和

看上去就不好做

先考虑对于确定的 m 节点的位置, 如何计算花费

好吧看起来不可做

那么开始骗

对于 2030% 的数据, 我们讨论 m 个点的分布 O(2n) , 计算答案需要枚举集合点 x O(n) , 然后求路径长度之和 O(m)

对于 m=2 的情况下, 集合点即为 LCA , 怎么求?
不会, 直接不要了

对于链的情况下, 选取中间的点作为集合点一定最优, 那么对于每一个集合点, 我们考虑

算了只要 2030%

实现#

框架#

先在外层枚举选择点的情况, 然后进去计算

代码#

#include <bits/stdc++.h>
const int MAXN = 30;
const int MOD = 1e9 + 7;

int n, m;
int Sum = 0;

struct Tree
{
    struct node {
        int to, next;
    } Edge[MAXN << 1];
    int head[MAXN], Edge_cnt;
    void head_init() { for (int i = 1; i <= n; i++) head[i] = -1; }

    void addedge(int u, int v) {
        Edge[++Edge_cnt].to = v, Edge[Edge_cnt].next = head[u];
        head[u] = Edge_cnt;
    }
} tree;

bool tag[MAXN]; // 标记是否有点

int Ans = 0;
int NowAns = 0;
void dfs(int now, int dep, int fa) {
    if (tag[now]) (NowAns += dep) %= MOD;
    for (int i = tree.head[now]; ~i; i = tree.Edge[i].next) {
        int nowto = tree.Edge[i].to;
        if (nowto == fa) continue;
        dfs(nowto, dep + 1, now);
    }
}

void solve(int State)
{
    int cnt = 0;
    memset(tag, false, sizeof(tag));
    while (State) {
        if (State & 1) tag[++cnt] = true;
        else tag[++cnt] = false;
        State >>= 1;
    }

    Ans = 0x3f3f3f3f, NowAns = 0;

    /*外层枚举集合点*/
    for (int i = 1; i <= n; i++) {
        NowAns = 0;
        dfs(i, 0, -1);
        Ans = std::min(Ans, NowAns);
    }
}

int main()
{
    scanf("%d %d", &n, &m);
    tree.head_init();
    for (int i = 1; i < n; i++) {
        int read; scanf("%d", &read);
        tree.addedge(i + 1, read), tree.addedge(read, i + 1);
    }

    /*外层枚举点的情况*/
    for (int State = 0; State < (1 << n); State++) {
        if (std::__popcount(State) != m) continue;

        solve(State);
        (Sum += Ans) %= MOD;
    }

    printf("%d", Sum);

    return 0;
}

T3

粗略看一下部分分很足

直接开始, 很显然的我们可以 O(ωλ2) 的枚举时间, 其中 ω=24,λ=60

然后我们就可以计算此时的答案, 这个的复杂度是 O(ωλ2n)

但我时间可能不够了, 模拟题你是坠棒的

所以简单的考虑一下 40%

总结

怎么会有 T3 放模拟的题啊???

这我骗鸡毛啊

留了 30 min 来看 T3 结果是模拟????

posted @   Yorg  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
more_horiz
keyboard_arrow_up light_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示