首页 > 其他分享 >12.17 CW 模拟赛 赛时记录

12.17 CW 模拟赛 赛时记录

时间:2024-12-18 18:43:11浏览次数:4  
标签:赛时 int 30 12.17 集合点 rm mathcal CW MAXN

前言

这一次又来更新比赛策略

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

回去吃点感冒药

看题

怎么 \(\rm{T1 \ T2}\) 是一个题

\(\rm{T1}\) 可能是 \(\rm{dp}\) 题

\(\rm{T3}\) 有些不好做

\(\rm{T4}\) 这种题一般都不会做, 能骗多少是多少

\(\rm{T1}\)

思路

转化题意

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

本身就很像 \(\rm{dp}\) , 我们考虑推一下朴素的方程

令 \(f_{i, j}\) 表示考虑到第 \(i\) 个人, 此时两个组织间的 \(\sum w\) 之差为 \(j\) , 最大的精彩度

考虑转移,

\[f_{i, j} = \begin{cases} \begin{aligned} & f_{i - 1, j} \\ & f_{k, j \pm w_i} + v_i \\ \end{aligned} \end{cases}\\ \]

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


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


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

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

整个的复杂度为 \(\mathcal{O} (n^2w)\)

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

实现

框架

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

代码

#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;
}

预期得分 : \(30 \rm{pts}\)

\(\rm{T2}\)

思路

转化题意,

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

看上去就不好做

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

好吧看起来不可做

那么开始骗

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

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

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

算了只要 \(20 \sim 30 \%\)

实现

框架

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

代码

#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;
}

\(\rm{T3}\)

粗略看一下部分分很足

直接开始, 很显然的我们可以 \(\mathcal{O} (\omega \lambda^2)\) 的枚举时间, 其中 \(\omega = 24, \lambda = 60\)

然后我们就可以计算此时的答案, 这个的复杂度是 \(\mathcal{O} (\omega \lambda^2 n)\)

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

所以简单的考虑一下 \(40 \%\)

总结

怎么会有 \(\rm{T3}\) 放模拟的题啊???

这我骗鸡毛啊

留了 \(30 \ \rm{min}\) 来看 \(\rm{T3}\) 结果是模拟????

标签:赛时,int,30,12.17,集合点,rm,mathcal,CW,MAXN
From: https://www.cnblogs.com/YzaCsp/p/18615664

相关文章

  • 12.17
    实验4NoSQL和关系数据库的操作比较 1.实验目的(1)理解四种数据库(MySQL、HBase、Redis和MongoDB)的概念以及不同点;(2)熟练使用四种数据库操作常用的Shell命令;(3)熟悉四种数据库操作常用的JavaAPI。2.实验平台(1)操作系统:Linux(建议Ubuntu16.04或Ubuntu18.04);(2)Hadoop版本:3.1.3;(3)My......
  • 12.17学习总结
    1.结构体学习(学完哒)    2.写了英语作业~ 3.p1162题代码已经敲出来哒,但是运行仍存在问题,我需再努力下 ......
  • 2024.12.17
    根据您提供的代码和错误信息,问题在于您尝试将Page<Policy>对象直接传递给page方法,但是page方法期望的是一个实现了IPage接口的对象。Page类是IPage接口的一个实现,所以您可以直接使用Page类,但是需要确保您使用的是正确的类型参数。您的代码中出现的错误提示表明,您可......
  • 12.17
    1.C++ 程序只需要表现得好像语句是按照顺序执行的。C++ 编译器和计算机自身只要能够确保每次计算的含义都不会改变,就可以改变执行顺序使程序运行得更快。自 C++11 开始,C++ 不再认为只有一个执行地址。C++ 标准库现在支持启动和终止线程以及同步线程间的内存访问。在 C+......
  • 12.17 CW 模拟赛 T4. 记忆碎片
    思路转化题意,问你在一个带权无向完全图中,如何填上\(w_i\in\left[1,\frac{n\cdot(n-1)}{2}\right]\),使得其最小生成树上的边权为给定的\(n-1\)个数考虑模仿\(\rm{kruskal}\)的方式,令\(f_S\)表示当前点集为\(S\),每次转移,如果当前边权需要在最小生......
  • 12.17随笔
    这里是12.17随笔UML图绘制--类图:https://blog.csdn.net/Qhx20040819/article/details/132268512?ops_request_misc=%257B%2522request%255Fid%2522%253A%252238d718ecb9472f600fa9689ab6e986fb%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=38d......
  • java面试问题(2024.12.17)
    记录java岗面试问题对java的了解Java是一门面向对象的编程语言,吸收了C++语言中大量的优点,但又抛弃了C++中容易出错的地方,如垃圾回收。Java又是一门平台无关的编程语言,通过java虚拟机(jvm)可以实现一次编译,处处运行。对jvm的了解Java虚拟机,是Java实现跨平台的关键所......
  • 12.17日报
    今天完成软件案例分析实验,以下为部分实验内容:packagecom.gdpu.controller;importcom.baomidou.mybatisplus.core.conditions.query.QueryWrapper;importcom.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;importcom.baomidou.mybatisplus.core.metadata.......
  • 12.12 CW 模拟赛 T3. 消除贫困
    思路朴素容易发现一个人资金变化是这样的:对于\(op=1\)的情况,会将其直接变成\(x\)对于\(op=2\)的情况,将其变成\(\max(x,当前值)\)直接用线段树暴力的维护即可巧妙容易发现\(op=2\)相当于一个大保底,我们先倒着处理出每个人到\(i\)位置至少有多少......
  • 12.12 CW 模拟赛 T1. 理想路径
    前言作为一个别的不行抗伤无敌的\(\rm{man}\),区区反向\(\rm{rk\1}\)不足为惧\(\rm{HD0X}\)巨佬场切\(2700\),\(\%\%\%\)思路朴素先把考场上一些基础的想法搬过来考虑一个环什么时候会导致产生字典序负环,这个好像还比较显然,就是如果出去的那个点的字典序小......