当前位置: 首页 > news >正文

题解:P13535 [IOI 2025] 纪念品(souvenirs)

好像不是特别难?

题意:现在有 \(0,1,\cdots n-1\)\(n\) 个物品,满足价格 \(p_0>p_1>\cdots p_{n-1}\),现在告诉你 \(0\) 号物品的价格 \(p_0\)

你可以进行至多 \(5000\) 次操作,每次操作如下:

  • 你选择一个数 \(V\),然后有一个人会用 \(V\) 块钱,从 \(0\) 开始往后买,当前物品能买就只买一个,否则不买,然后到下一个物品,交互库会告诉你哪些号被买了,还剩下多少钱。每次操作必须买到一个物品。

现在你需要操作之后,满足第 \(i\) 个物品被买了 \(i\) 次。\(n\le 100\)

做法:

首先发现这个 \(5000\) 次没啥用,因为每次一定买一个最多也用不到 \(5000\) 次。给这么宽的限制感觉完全可以你把数都解出来再按次数补上。通过一次操作我可以知道物品的一个线性组合和为多少,可以通过这个弄一个满秩的矩阵然后解出来。

然后考虑第一次咋办,我们想一个问题,如果直接 \(p_i=p_{i-1}-1\),那么如果我们选的数太小,这一轮买不到物品就爆炸了,得选的大一点,不妨我们就直接是 \(p_0-1\)

然后好像不太会做了,看看部分分 \(n=3\) 咋做,如果只买了 \(1\) 那么直接可以算出来 \(1\) 的大小,然后就可以再问一次算出来 \(2\);如果同时买了 \(1,2\),那就不太好做了,我们需要问一个 \(1\) 一定买不到的数,同时买得到 \(2\)。那么假设 \(1,2\) 的代价和为 \(V\),因为 \(p_1>p_2\),我买 \(\frac{V}{2}\) 的话,这样就可以分辨出来了,解决了 \(n=3\) 的问题。

这启发了我们一个事情,当我们问出来一个集合 \(S\) 和为 \(V\),这里 \(S\) 集合里的数我还未知,因为已知我就可以直接把 \(V\) 减掉即可,我们可以问一个 \(\frac{|S|}{V}\),这样就可以保证一定有元素被选出来,且最大值一定不会被选进来。

同时,我们发现,如果这样一直问,我可以很方便的构造一个上三角矩阵,因为如果我有矩阵的一行,我就可以按上面的这个方式问,这样递归下去就可以解出来一些元素。同时上三角矩阵这个性质让我们一定不会问得超过一个元素的次数上限。

当我根据目前的方程组解出来一些元素之后,我就可以再找一个位置 \(x\) 满足 \(x\) 的价格已知,\(x+1\) 价格未知,然后问一个 \(p_x-1\),再去解后面的。

这个题就做完了,记得写代码的时候把 long long 开明白。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 105;
#include <utility>
#include <vector>
std::pair<std::vector<int>, long long> transaction(long long M);
//std::pair<std::vector<int>, long long> transaction(long long M);
int n;
long long p[maxn];
int cnt[maxn];
void solve(long long V) {pair<vector<int>, long long> res = transaction(V);vector<int> id = res.first, tp; long long rest = V - res.second;for (int i = 0; i < id.size(); i++)cnt[id[i]]--;if(!p[id[0]]) {for (int i = 0; i < id.size(); i++)if(p[id[i]])rest -= p[id[i]];elsetp.push_back(id[i]);while(tp.size() > 1) {solve(rest / tp.size());while(p[tp[tp.size() - 1]])rest -= p[tp[tp.size() - 1]], tp.pop_back();}p[id[0]] = rest;}int pos = id[0];while(pos < n && p[pos + 1])pos++;if(pos < n)solve(p[pos] - 1);}
void buy_souvenirs(int N, long long P0) {n = N, p[0] = P0;for (int i = 1; i < n; i++)cnt[i] = i;n--;solve(P0 - 1);for (int i = 1; i <= n; i++)while(cnt[i]--)transaction(p[i]);
}
http://www.jsqmd.com/news/387304/

相关文章:

  • 【UI自动化测试】4_web自动化测试 _元素定位(重点)
  • Python数据分析:时间序列数据分析
  • 鱼类异常状态检测数据集VOC+YOLO格式3895张2类别
  • 算法学习日记 | 双指针
  • Spring注解方式整合Mybatis
  • @Import整合第三方框架原理
  • 使用 Google Earth Engine 快速导出 Copernicus GLO-30 和 ASTER GDEM 高程数据
  • 现代控制理论(1)—— 概论
  • 05]delphi10.3中richedit中删除线
  • 关于学习技术栈的思考
  • 实测才敢推!自考必备的降AI率平台 —— 千笔·专业降AIGC智能体
  • 【Python】从0到1完成轻量级接口测试工具:基于Python+FastAPI+Pytest
  • 适用于室内和室外的集成式LED PCBA解决方案
  • 基础入门 Flutter for OpenHarmony:battery_plus 电池状态监控详解
  • ArcPy 脚本:批量生成郑州市 1990-2019 年空间分析结果(核密度、热点、平均中心、标准差椭圆)
  • 这次终于选对!圈粉无数的一键生成论文工具 —— 千笔AI
  • 2026年阿里巴巴/1688平台开户代运营权威评测:深圳昊客网络 脱颖而出 - 深圳昊客网络
  • WAC集团推出WAC建筑品牌,以先进、技术驱动的解决方案赋能照明设计师
  • 使用 ArcPy 批量裁剪建筑面矢量:根据城区边界提取城市建筑数据
  • 2026最新!千笔,专科生专属降AI神器
  • 毕业论文神器!千笔,备受喜爱的AI论文平台
  • Windows Powershell 打开即闪退 | Windows PowerShell 内部错误。加载托管的 Windows Powershell 失败,返回错误 80131018。
  • 强烈安利!千笔,口碑爆棚的一键生成论文工具
  • 服务器运维(四十)日服务器linux-ps分析工具—东方仙盟
  • 用 Python 批量提取 1990–2019 年高层建筑并按城市导出 Shapefile
  • delphi10.3中UpDown1使用
  • 【信息科学与工程学】【智能交通】第五篇 自动驾驶02
  • 看完就会:AI论文平台,千笔 VS 灵感风暴AI,本科生写作神器!
  • vue3+nodejs校园活动管理系统的设计与实现
  • 人工智能之核心基础 机器学习 第十八章 经典实战项目 - 实践