【BZOJ4428】[Nwerc2015]Debugging调试【DP】【记忆化搜索】【分块】

14 篇文章 0 订阅
10 篇文章 0 订阅

【题目链接】

题解:

最坏情况指的是出错位置始终在最长的区间里。为了使时间最少,我们每次一定是尽量均分区间。

设dp[n]表示,在最坏情况下,处理n行代码所需要的最少时间。

那么有

dp[n] = min{(i - 1) * p + dp[ceil(n / i)]} + r

意义是,将n行代码分成i块,那么需要加i - 1个printf,然后对最长的区间递归处理。

直接枚举i是O(n^2)的。

优化在对i的枚举,因为ceil(n / i)的取值最多有O(sqrt(n))种,而且取值相同的i都在连续的一段内,那么为了花费最小,我们肯定是取最小i。(类似的问题在【【SPOJ-NAGAY】Joseph’s Problem】遇到过,那个问题是floor(n / i))

然后我们就要推导下标啦。

总之就是要解这个方程

x、i、n为非负整数,已知n、i,求最小的x


有两种方法

第一种:看Claris博客,得到x = (n - 1) / ((n - 1) / i) + 1(这里的除均为整除)

第二种:

首先要知道


(具体数学里面有)

带入,得到


同乘上x


因为我们要求x的最小值,所以我们只看左边的不等式


因为x为非负整数,左边不一定是整数,那么x的最小值应该是



复杂度:

时间复杂度:O(n^(3/4))(不会分析...),空间复杂度:O(n)


GET:

多推公式


/* Telekinetic Forest Guard */
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long LL;

const int maxn = 1000005;

int n, r, p;
LL dp[maxn];

inline int iread() {
	int f = 1, x = 0; char ch = getchar();
	for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1;
	for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
	return f * x;
}

inline int ceil(int x, int b) {
	return (x + b - 1) / b;
}

inline LL dfs(int x) {
	if(x <= 1) return 0;
	if(dp[x]) return dp[x];
	LL res = (LL)(x - 1) * p;
	for(int i = 2; i < x; i = ceil(x, (ceil(x, i) - 1)))
		res = min(res, (LL)(i - 1) * p + dfs(ceil(x, i)));
	return dp[x] = res + r;
}

int main() {
	n = iread(); r = iread(); p = iread();
	printf("%lld\n", dfs(n));
	return 0;
}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值