梦熊十三联测 D题 电报

这道题感觉类似诈骗题,可以很轻松的猜到一个假结论,可以试试以下数据

这道题可以使用一棵(类似于哈夫曼树的)二叉树来进行编码。每个非叶子节点的两条子边权值分别为1和2。每个叶子节点对应了一个字符,其代价即为根到该叶子结点的路径长度。

最优解中出现频次越大的字符串深度越小,考虑由浅入深构造整棵二叉树。

可以设f[i] [a] [b] [l] 表示构造二叉树的深度为i,其中深度为i-1的节点有a个,深度为i的节点有b个,深度不超过i-2的叶子有l个。我们可以枚举深度i-1保留k个节点作为叶子,将剩下的节点扩展。由此可以得到O(n^5)的做法

那这样做肯定是会超时的,我们要考虑优化做法

转移时不需要记录深度(将贡献拆分到每一层),可以减少一维做到O(n^4)

进一步将枚举的过程省略,将其拆分为两种转移:扩展一个节点,或者将深度加一。

优化后的时间复杂度为O(n^3)

这道题暴力做法能拿到30pts(果真是暴力出奇迹)

#include <bits/stdc++.h>
using namespace std;
#define int long long
inline int lowbit(int x) { return x & (-x); }
int n, a[100010], dp[100010], s[100010], sum[100010];
signed main() {
    freopen("telegram.in", "r", stdin);
    freopen("telegram.out", "w", stdout);
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> a[i];
    for (int i = 1; i <= n; i++) s[1 << (i - 1)] = i;
    sum[0] = 0;
    for (int msk = 1; msk < (1 << n); msk++) sum[msk] = sum[msk ^ lowbit(msk)] + a[s[lowbit(msk)]];
    memset(dp, 0x3f, sizeof(dp));
    for (int i = 1; i <= n; i++) dp[1 << (i - 1)] = 0;
    for (int msk = 1; msk < (1 << n); msk++) {
        for (int c = (msk - 1) & msk; c; c = (c - 1) & msk) {
            dp[msk] = min(dp[msk], dp[c] + dp[msk ^ c] + sum[c] + 2 * sum[msk ^ c]);
        }
    }
    cout << dp[(1 << n) - 1];
    return 0;
}

AC代码:

#include <bits/stdc++.h>
#define ALL(x) begin(x), end(x)
#define All(x, l, r) &x[l], &x[r] + 1
using namespace std;
void file() {
    freopen("telegram.in", "r", stdin);
    freopen("telegram.out", "w", stdout);
}
using ll = long long;

const int kL = 405, inf = (1 << 30) - 3;
int n;
array<int, kL> a, pre;
array<array<array<array<int, kL>, kL>, 40>, 2> f;

void chkmn(int& x, int y) { (x > y) && (x = y); }

int main() {
    file();
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> a[i];
    sort(All(a, 1, n));
    for (int i = 1; i <= n; i++) pre[i] = pre[i - 1] + a[i];
    for (auto& A : f)
        for (auto& B : A)
            for (auto& k : B) k.fill(inf);
    f[1][1][0][1] = -a[1];
    for (int i = 1; i <= n; i++) {
        int cr = (i & 1), nx = !(i & 1);
        for (int j = 1; j < 38; j++)
            for (int k = 0; k <= i; k++) fill(All(f[nx][j][k], 0, i), inf);
        for (int j = 1; j < 38; j++)
            for (int k = 0; k <= i; k++) {
                for (int p = k; p + k <= i; p++) chkmn(f[cr][j + 1][p - k][k], f[cr][j][k][p]);
                for (int p = 0; p + k <= i; p++) chkmn(f[nx][j][k][p + 1], f[cr][j][k][p] - j * a[i + 1]);
            }
    }
    ll ans = inf, sum = accumulate(All(a, 1, n), 0ll);
    for (int i = 1; i < 38; i++) ans = min(ans, sum * i + f[n & 1][i][0][1]);
    cout << ans << "\n";
    return 0;
}

### 产品联合试流程和注意事项 产品联合试(简称“联测”)是软件开发过程中一个关键环节,特别是在多个团队或模块协同开发的场景中。其主要目的是验证不同模块、系统或服务之间的接口是否能够正确交互,确保整体功能的完整性和稳定性。 #### 联测流程 1. **需求对齐与试计划制定** 在联测开始前,各方需对产品需求、功能边界、接口规范进行明确,并制定详细的试计划,包括试范围、试用例设计、试环境准备、试时间安排等。 2. **接口文档准备与评审** 各方需提供完整的接口文档,包括请求方式、参数说明、返回值格式、错误码定义等。通过文档评审确保接口设计合理且无歧义。 3. **试环境搭建与接口联调** 搭建与生产环境尽可能一致的试环境,进行接口联调。此阶段主要验证接口是否能正常通信,响应是否符合预期。 4. **执行试用例与缺陷管理** 根据试计划执行试用例,记录试结果。发现缺陷后需及时提交并跟踪修复情况,确保问闭环。 5. **回归试与验收确认** 缺陷修复后进行回归试,验证问是否彻底解决。最终由相关方确认试结果,完成联测交付。 6. **联测总结与文档归档** 联测结束后进行总结,分析试过程中的问与经验,归档试文档,为后续维护和升级提供依据。 #### 注意事项 - **接口一致性** 确保接口在开发与试阶段保持一致性,避免因接口变更导致试失败。如有变更,应及时同步文档并通知相关方。 - **数据隔离与安全性** 试数据应与生产数据隔离,防止试行为影响真实业务。同时需注意敏感数据的脱敏处理。 - **异常处理与容错机制** 需对接口异常情况进行试,如超时、参数错误、服务不可用等,确保系统具备良好的容错能力。 - **日志与监控** 联测过程中应开启详细的日志记录,便于问定位。建议引入监控工具,实时观察接口调用状态与性能。 - **沟通与协作机制** 联测涉及多方协作,需建立高效的沟通机制,及时处理试中发现的问,避免因沟通不畅影响进度。 - **自动化试支持** 建议在联测阶段引入自动化试工具,提升试效率与覆盖率,尤其适用于回归试。 #### 示例:接口联测试用例(伪代码) ```python def test_api_response(): # 请求参数 payload = { "user_id": 12345, "token": "abc123xyz" } # 发起请求 response = api_client.post("/user/profile", data=payload) # 验证响应状态码 assert response.status_code == 200 # 验证返回数据结构 assert "username" in response.json() assert "email" in response.json() # 验证错误处理 invalid_payload = {"user_id": None} error_response = api_client.post("/user/profile", data=invalid_payload) assert error_response.status_code == 400 ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值