news 2026/8/8 10:37:19

P1566 加等式 【洛谷算法习题】

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
P1566 加等式 【洛谷算法习题】

P1566 加等式

网页链接

P1566 加等式

题目描述

对于一个整数集合,我们定义“加等式”如下:集合中的某一个元素可以表示成集合内其他元素之和。如集合1 , 2 , 3 {1,2,3}1,2,3中就有一个加等式:3 = 1 + 2 3=1+23=1+2。而且3 = 1 + 2 3=1+23=1+23 = 2 + 1 3=2+13=2+1是相同的加等式,也是这个集合唯一的加等式。给定一个整数集合,编程找出其加等式的个数。

输入格式

第一行为t tt,表示测试数据组数。

接下来t tt行,每行表示一组测试数据。其中第一个数m mm,表示集合元素的个数,接下来m mm个不同的整数x i x_ixi,表示集合元素。

输出格式

对于每个输入数据,输出一个整数,表示其中加等式的个数。

输入输出样例 #1

输入 #1

3 3 1 2 3 3 1 2 5 6 1 2 3 5 4 6

输出 #1

1 0 7

说明/提示

1 ≤ t ≤ 10 1\le t\le 101t101 ≤ m ≤ 30 1\le m \le 301m301 ≤ x ≤ 1000 1\le x\le 10001x1000

解题思路

本题要求统计一个集合中“加等式”的数量,即存在一个元素等于集合中其他元素之和。由于数据规模较小(m ≤ 30 m\le 30m30,元素值≤ 1000 \le 10001000),可以采用子集和 DP的思想,先将元素排序,然后依次枚举每个元素作为“和”,利用背包 DP 统计用前面较小的元素组成该数的方案数,并累加答案。

1. 问题等价转化
  • 加等式定义:集合中某个元素x xx可以表示为集合中若干个其他元素之和。注意“其他元素”不能包含x xx自身,且组合不考虑顺序(即{ a , b } \{a,b\}{a,b}{ b , a } \{b,a\}{b,a}视为同一种)。
  • 计数策略:将元素从小到大排序,依次考虑每个元素a i a_iai。此时,所有可能参与求和组成a i a_iai的元素一定来自a 1 ∼ a i − 1 a_1 \sim a_{i-1}a1ai1(严格小于a i a_iai)。如果我们能计算出用前i − 1 i-1i1个元素组成和为a i a_iai的不同子集个数,那么这些方案就对应以a i a_iai为“和”的加等式。
  • 子集和 DP:维护一个数组f [ v ] f[v]f[v]表示当前已考虑的元素中,选出若干元素(每个最多一次)其和恰好为v vv的方案数。顺序扫描元素,对于当前元素a i a_iaif [ a i ] f[a_i]f[ai]即为组成a i a_iai的加等式个数(由前面的元素构成)。累加后,再将a i a_iai加入 DP 的候选集合中(更新f ff),供后续更大的元素使用。
2. 算法实现(排序 + 背包 DP)
  1. 输入与排序:读取集合大小m mm和所有元素,计算元素总和s u m sumsum(用于 DP 上限)。将元素按升序排序,保证前面元素总是小于后面的。
  2. DP 初始化f [ 0 ] = 1 f[0]=1f[0]=1,其余为0 00,表示空集和为0 00的方案数为1 11
  3. 遍历元素i = 1 ∼ m i = 1 \sim mi=1m):
    • 累加答案a n s + = f [ a i ] ans \mathrel{+}= f[a_i]ans+=f[ai]。此时f ff仅由a 1 ∼ a i − 1 a_1 \sim a_{i-1}a1ai1更新过,因此f [ a i ] f[a_i]f[ai]恰好是用严格小于a i a_iai的元素组成a i a_iai的方案数。
    • 更新 DP:将当前元素a i a_iai加入背包。为防止同一个元素被重复使用,需倒序更新:for j = sum down to a_i: f[j] += f[j - a_i]
  4. 输出答案:每组数据处理完后输出a n s ansans
3. 复杂度分析
  • 时间复杂度:每组数据需要进行m mm次 DP 更新,每次更新规模为O ( s u m ) O(sum)O(sum)m ≤ 30 m \le 30m30s u m ≤ 30 × 1000 = 30000 sum \le 30 \times 1000 = 30000sum30×1000=30000,单组复杂度约9 × 10 5 9 \times 10^59×105。共t ≤ 10 t \le 10t10组,总操作量不到10 7 10^7107,轻松通过。
  • 空间复杂度O ( s u m ) O(sum)O(sum)用于 DP 数组,s u m sumsum最大30000 3000030000,空间极小。

总结

巧妙地将“加等式”计数转化为有序子集和问题:排序后,每个元素作为和时,其组合只能来自更小的元素,通过背包 DP 统计组合方案数。先统计答案再更新 DP 的方式确保了当前元素不会被自己用来组合自己。该方法简洁高效,完美契合数据范围。

代码简要说明

  1. 输入处理:读入t tt,对每组数据读入m mm和数组a aa,计算总和s u m sumsum,并对a aa排序。
  2. DP 数组f[30010]存储组合方案数,初始f[0]=1
  3. 核心循环:遍历排序后的a i a_iai,先将f[a[i]]加入答案,然后倒序更新ff[j] += f[j - a[i]]j jjs u m sumsum降到a i a_iai)。
  4. 输出:输出ans,每组数据后换行。

代码内容

#include<bits/stdc++.h>usingnamespacestd;#defineendl'\n'typedeflonglongll;typedefunsignedlonglongull;typedefvector<vector<ll>>vvt;typedefpair<ll,ll>pll;constll N=1e3+10;constll INF=1e18;constll M=1e6+10;constll mod=1e9+7;ll t,m;ll a[40];ll f[30010];ll sum;intmain(){ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);cin>>t;while(t--){cin>>m;sum=0;for(ll i=1;i<=m;i++){cin>>a[i];sum+=a[i];}sort(a+1,a+m+1);memset(f,0,sizeof(f));f[0]=1;ll ans=0;for(ll i=1;i<=m;i++){ans+=f[a[i]];for(ll j=sum;j>=a[i];j--)f[j]+=f[j-a[i]];}cout<<ans<<endl;}return0;}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/8 10:36:38

Firefox专属:Sketchfab 3D模型免费下载终极指南

Firefox专属&#xff1a;Sketchfab 3D模型免费下载终极指南 【免费下载链接】sketchfab sketchfab download userscipt for Tampermonkey by firefox only 项目地址: https://gitcode.com/gh_mirrors/sk/sketchfab 想要在Sketchfab平台上免费获取高质量的3D模型吗&#…

作者头像 李华
网站建设 2026/8/8 10:35:10

Kubernetes集群管理演进:从自建到现代云原生的转变

1. 为什么自建K8s集群正在成为历史记得2018年我第一次在本地数据中心部署Kubernetes集群时&#xff0c;光是etcd集群的调优就花了整整两周。当时为了确保生产环境的高可用&#xff0c;我们团队不得不维护三个master节点、五个worker节点&#xff0c;外加一套复杂的监控告警系统…

作者头像 李华
网站建设 2026/8/8 10:35:10

HOOPS Mesh SDK 26.6.0

用于无故障网格生成的 CAE SDK,使用值得信赖的可靠 2D 和 3D 网格划分功能构建您的 CAE 应用程序。HOOPS Mesh 提供精确的谓词技术和一流的边界恢复功能&#xff0c;实现无与伦比的精度。功能强大的网格划分工具包 HOOPS Mesh 拥有超过 20 年的经验&#xff0c;是 CAE 开发人员…

作者头像 李华
网站建设 2026/8/8 10:33:38

VC++任务栏图标开发全解析:从Windows API到实战应用

1. 项目概述&#xff1a;为什么VC任务栏图标开发依然重要 在Windows桌面应用开发领域&#xff0c;任务栏图标&#xff08;或称系统托盘图标&#xff09;是一个看似微小却至关重要的用户交互界面。它不仅是应用程序在后台运行的“灯塔”&#xff0c;更是实现快捷操作、状态通知和…

作者头像 李华
网站建设 2026/8/8 10:32:17

C++多态机制:从虚函数表到现代实现

1. C多态的本质与实现原理 多态是面向对象编程的三大特性之一&#xff08;封装、继承、多态&#xff09;&#xff0c;它允许不同类的对象对同一消息做出不同响应。在C中&#xff0c;多态主要通过虚函数机制实现&#xff0c;其核心原理可以概括为&#xff1a; 静态多态&#xf…

作者头像 李华
网站建设 2026/8/8 10:31:42

Windows 11 25H2下WPS卡死问题排查与解决方案

1. 问题现象与初步排查 Windows 11 25H2系统环境下WPS Office频繁出现"未响应"状态&#xff0c;即使在执行了msconfig纯净启动后问题依然复现。这个现象在技术社区已经引发广泛讨论&#xff0c;根据用户反馈统计&#xff0c;该问题在25H2版本中的出现概率显著高于之前…

作者头像 李华