[dp]最优除法

问题描述

请你通过若干次除法将一个数字 x x x 变得不超过 y y y

现在有很多个除数可以选择,给定一个长度为 n n n 的序列 b b b。表示除数 i i i 的花费是 b i b_i bi, 你可以用这个除数把 x x x 变为 x / i x / i x/i。每种除数可以使用无限次。

多组询问,每组询问输入两个数 x , y x, y x,y,表示需要使用若干次除法把 x x x 变得不超过 y y y,对于每一组询问你都要输出一个答案表示求最小花费,保证题目一定有解。

输入格式

输入包含 q + 2 q + 2 q+2 行。
第一行输入两个正整数 n , q n, q n,q
第二行输入 n n n 个正整数,第 i i i 个数表示 b i b_i bi。 接下来 q q q 行,每行两个正整数 x , y x, y x,y,如题意所示。

输出格式

输出 q q q 行。 每行输出一个数,表示对应询问的答案。

样例

样例输入1:

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

样例输出1:

2 
0 
2

数据范围

对于 20 % 20\% 20% 的数据, 1 ≤ n , q , x , y ≤ 1 0 2 1 \le n, q, x, y \le 10^2 1n,q,x,y102
对于 40 % 40\% 40% 的数据, 1 ≤ n , q , x , y ≤ 1 0 3 1 \le n, q, x, y \le 10^3 1n,q,x,y103
对于 100 % 100\% 100% 的数据, 1 ≤ n , q , x , y ≤ 1 0 5 1 \le n, q, x, y \le 10^5 1n,q,x,y105 1 ≤ b i ≤ 1 0 9 1 \le b_i \le 10^9 1bi109

题解

首先,我们考虑正着想,用 d p i dp_{i} dpi 表示到 i i i 的最小花费。
因此, d p i = d p x / k + a k dp_{i} = dp_{x / k} + a_k dpi=dpx/k+ak,复杂度为 O ( n 2 × T ) O(n^2 \times T) O(n2×T)
由于多组数据, x x x 不同,因此每次都要算一下 d p dp dp 数组,不能进行预处理。
也可以写记忆化搜索,比 dp 稍快,能得 50 50 50 分。

考虑反向思考,从 1 1 1 开始乘, d p i dp_{i} dpi 表示造成 i i i 点削减的最小花费。
初始化 d p i = min ⁡ ( d p j ) { 1 ≤ j ≤ n } dp_{i} = \min(dp_{j})\{1 \le j \le n\} dpi=min(dpj){1jn}
接下来完全背包预处理,结束时同样进行上面操作即可。

对于每次询问,只需找出 ⌊ x p ⌋ ≤ y \lfloor\frac{x}{p}\rfloor \le y pxy p p p 的最小值即可。
可以使用二分和直接计算。
二分单调性证明: d p i = min ⁡ ( d p j ) { 1 ≤ j ≤ n } dp_i = \min(dp_j)\{1 \le j \le n\} dpi=min(dpj){1jn},对于 d p i dp_i dpi d p i + 1 dp_{i + 1} dpi+1 d p i + 1 dp_{i + 1} dpi+1 一定小于等于 min ⁡ ( d p i + 1 , d p i ) \min(dp_{i + 1}, dp_i) min(dpi+1,dpi)

memset(a, 0x3f, sizeof(a));
输入
for(int i = n - 1; i >= 1; -- i){
	a[i] = min(a[i], a[i + 1]);
}
//dp
for(int i = 1; i <= 100000; ++ i){
	for(int j = 1; j <= 100000 / i; ++ j){
		a[i * j] = min(a[i * j], a[i] + a[j]);
	}
}
for(int i = 1e5 - 1; i >= 1; -- i){
	a[i] = min(a[i], a[i + 1]);
}
a[1] = 0;
while(q --){
	int x, y;
	scanf("%d %d", &x, &y);
	printf("%d\n", a[x / (y + 1) + 1]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值