将题意转换为一开始\(t = 0\),第\(i\)个操作是令\(t \leftarrow (a_i + 1) t + (a_i + b_i + 1)\)。记\(A_i = a_i + 1, B_i = a_i + b_i + 1\)。问经过最多经过多少次操作后才能使得进行完这些操作后\(t \leq T\)仍然满足。

我们先推一个贪心性质:

若先进行\(i\)操作,再进行\(j\)操作时满足条件,且\(\frac{A_i - 1}{B_i} < \frac{A_j - 1}{B_j}\),则可以交换\(i\),\(j\)操作的顺序,使得条件仍然满足。

证明:由单调性,只需证明先进行\(i\)操作再进行\(j\)操作后的\(t\)的值大于先进行\(j\)操作再进行\(i\)操作后\(t\)的值。假设一开始的数值为\(t\),则第一种操作组合后,数值为\(A_iA_jt + A_jB_i + B_j\),第二种操作组合后数值为\(A_iA_jt + A_iB_j + B_i\)。

由于\(A_jB_i + B_j > A_iB_j + B_i\)等价于\(\frac{A_i - 1}{B_i} < \frac{A_j - 1}{B_j}\),故结论成立!

因此我们可以将这些操作按\(\frac{A_i - 1}{B_i}\)从大到小排序,然后设计一个DP。设\(f_{i, j}\)表示进行了前\(i\)种操作的\(j\)次后\(t\)的值最小是多少。我们可以得到一个\(O(n^2)\)做法。注意到我们必定先进行\(A_i > 0\)的操作,而这样的操作最多进行\(O(\log T)\)次。再进行\(A_i = 0\)的操作时,必定是按照\(B_i\)从小到大顺序进行。所以我们只需把\(A_i > 0\)的操作拿来\(DP\),并且第二维只考虑到\(O(\log T)\)即可获得一个\(O(n (\log n + \log T))\)时间的算法。

代码如下:

#include <bits/stdc++.h>
using namespace std; const int N = 200005, M = 40; template <class T>
void read (T &x) {
int sgn = 1;
char ch;
x = 0;
for (ch = getchar(); (ch < '0' || ch > '9') && ch != '-'; ch = getchar()) ;
if (ch == '-') ch = getchar(), sgn = -1;
for (; '0' <= ch && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
x *= sgn;
}
template <class T>
void write (T x) {
if (x < 0) putchar('-'), write(-x);
else if (x < 10) putchar(x + '0');
else write(x / 10), putchar(x % 10 + '0');
} int n, cnt1 = 0, cnt2 = 0;
long long a[N], b[N], f[N][M + 1], t; struct node {
long long A;
long long B;
bool operator < (node rhs) const {
long long val1 = (A - 1) * rhs.B;
long long val2 = (rhs.A - 1) * B;
return (val1 > val2) || (val1 == val2 && A < rhs.A);
}
} vec[N]; long long num[N], pre[N]; int main () {
read(n), read(t);
for (int i = 1; i <= n; i++) {
read(a[i]), read(b[i]);
if (a[i]) {
node x = {a[i] + 1, a[i] + b[i] + 1};
vec[++cnt1] = x;
}
else num[++cnt2] = b[i] + 1;
} sort(vec + 1, vec + cnt1 + 1);
sort(num + 1, num + cnt2 + 1); pre[0] = 0ll;
for (int i = 1; i <= cnt2; i++) pre[i] = pre[i - 1] + num[i]; for (int i = 0; i <= M; i++) f[0][i] = t + 1;
f[0][0] = 0ll; for (int i = 1; i <= cnt1; i++) {
for (int j = 0; j <= M; j++) {
f[i][j] = f[i - 1][j];
if (j) f[i][j] = min(f[i][j], vec[i].A * f[i - 1][j - 1] + vec[i].B);
}
} int ans = 0;
for (int i = 0; i <= M; i++) {
if (f[cnt1][i] > t) continue;
int pos = lower_bound(pre, pre + cnt2 + 1, t + 1 - f[cnt1][i]) - pre - 1;
ans = max(ans, pos + i);
}
write(ans), putchar('\n');
return 0;
}

Social Infrastructure Information Systems Division, Hitachi Programming Contest 2020 D题题解的更多相关文章

  1. Social Infrastructure Information Systems Division, Hitachi Programming Contest 2020 C题题解

    首先,我们将题目理解成若\(i\)与\(j\)距离恰好为\(3\),则不可能\(p_i \equiv p_j \equiv 1 \space or \space 2 (\bmod 3)\).这就相当于 ...

  2. HHKB Programming Contest 2020 D - Squares 题解(思维)

    题目链接 题目大意 给你一个边长为n的正方形和边长为a和b的正方形,要求把边长为a和b的正方形放在长度为n的正方形内,且没有覆盖(可以相邻)求有多少种放法(mod 1e9+7) 题目思路 这个思路不是 ...

  3. (寒假开黑gym)2018 ACM-ICPC, Syrian Collegiate Programming Contest(爽题)

    layout: post title: (寒假开黑gym)2018 ACM-ICPC, Syrian Collegiate Programming Contest(爽题) author: " ...

  4. M-SOLUTIONS Programming Contest 2020 题解

    M-SOLUTIONS Programming Contest 2020 题解 目录 M-SOLUTIONS Programming Contest 2020 题解 A - Kyu in AtCode ...

  5. 2021.7.27--Benelux Algorithm Programming Contest 2020 补提

    I Jigsaw 题目内容: 链接:https://ac.nowcoder.com/acm/contest/18454/I 来源:牛客网 You have found an old jigsaw pu ...

  6. Yahoo Programming Contest 2019 补题记录(DEF)

    D - Ears 题目链接:D - Ears 大意:你在一个\(0-L\)的数轴上行走,从整数格出发,在整数格结束,可以在整数格转弯.每当你经过坐标为\(i-0.5\)的位置时(\(i\)是整数),在 ...

  7. 2017 ACM Arabella Collegiate Programming Contest div2的题,部分题目写个题解

    F. Monkeying Around   维护点在多少个线段上 http://codeforces.com/gym/101350/problem/F 题意:有m个笑话,每个笑话的区间是[L, R], ...

  8. 带权并查集:CF-2015 ACM Arabella Collegiate Programming Contest(F题)

    F. Palindrome Problem Description A string is palindrome if it can be read the same way in either di ...

  9. atcoder Keyence Programming Contest 2020 题解

    比赛地址 A 题意:给一个\(n*m\)的初始为白色的矩阵,一次操作可以将一行或一列染成 黑色,问至少染出\(k\)个黑点的最少操作次数. \(n\),\(m\)<=100,\(k\)<= ...

随机推荐

  1. tcpack--3快速确认模式

    接收到数据报后,会调用tcp_event_data_recv(),不管是在慢速路径的tcp_data_queue中调用还是 在快速路径中处理接收数据后直接调用,注意(如果len <= tcp_h ...

  2. vue 切换主题(换肤)功能

    一:先写好两个css样式放在static文件夹中 二:在index.html中添加css link链接 <link rel="stylesheet" id="sty ...

  3. shell中数字、字符串、文件比较测试

    1.逻辑运算符:与&&     或||    非!  &&:双目操作符:与运算中:如果第一个数为假,结果一定为假   ==> 短路操作符 ||:双目操作符:或运算 ...

  4. Springboot 完整搭建快速入门,必看!

    前言 手把手教你Springboot微服务项目搭建快速入门,通过本文学习Springboot的搭建快速入门,掌握微服务大致的配置服务,后续将会继续将核心组件引入到项目中,欢迎关注,点赞,转发. Spr ...

  5. Spring中@Translational注解失效场景

    今天面试被问到@Translational注解什么场景下失效,我一脸懵逼,说的恍恍惚惚的,下来我就总结一下@Translational注解失效的场景! @Transactional 注解相信大家并不陌 ...

  6. 单线程的Redis有哪些慢动作?

    持续原创输出,点击上方蓝字关注我 目录 前言 为什么 Redis 这么火? 键和值的保存形式? 为什么哈希表操作变慢了? 集合的操作效率? 有哪些数据结构? 不同操作的复杂度? 总结 前言 现在一提到 ...

  7. php在线预览pdf文件

    话不多说,直接上代码 <?php public function read_pdf($file) { if(strtolower(substr(strrchr($file,'.'),1)) != ...

  8. Camtasia的标记使用方法

    相信大家都想过学习或者尝试过编辑视频,可能曾经也下载使用过微课录制软件Camtasia(win),或许现在也还在使用.小编现在也经常使用Camtasia录屏编辑视频,在编辑的过程中,总是会不小心在轨道 ...

  9. mongodb分页查询,排序

    mongodb代码 根据时间倒序,查看10条 db.表名.find({"_id":"xxx"}).sort({"inserted":-1}) ...

  10. JAVA面试宝典分享

    JAVA面试宝典分享 前言 面试题 Java面试题(上) Java面试题(中) Java面试题(下) 参考答案 其他补充内容: 项目经验 项目介绍 项目开发流程 项目管理 系统架构 第三方工具(插件) ...