20150124
20150125

BZOJ3136 [Baltic2013]brunhilda

laekov posted @ 2015年1月24日 21:32 in 未分类 with tags DP math bzoj , 826 阅读

决心写一道usaco之外的题,于是就挑中了这道。

 

为啥这编辑器有BUG,每次按回车要向下跳?

 

发现可以预处理DP。f_i表示第i个数被砍完需要最少多少刀。对于每一个i,设p_i是它的质因子里最大的一个在给定集合里的,那么它可以转移到(i+1,i+p_i)这个范围。然后f_i显然不减,所以用单调队列之类的玩意。

 

然后卡着时间限制过了。不知道前面那些秒跑的人是怎么搞的。

 

1	#include <cstdio>
2	#include <cstring>
3	#include <algorithm>
4	
5	using namespace std;
6	
7	const int maxn = 10000009;
8	const int maxm = 100009;
9	
10	int k[maxn], f[maxn], n, m, q, p[maxm], v[maxm];
11	
12	void pre(int n) {
13		sort(p, p + m);
14		memset(k, 0, sizeof(k));
15		for (int i = 0; i < m; ++ i)
16			if (!i || p[i] != p[i - 1])
17				for (int j = 0; j <= n; j += p[i])
18					k[j] = p[i];
19	
20		static int q[maxn];
21		int hd(0), tl(1);
22		q[0] = f[0] = 0;
23		for (int i = 1; i <= n; ++ i) {
24			while (hd < tl && i >= q[hd] + k[q[hd]])
25				++ hd;
26			if (hd == tl) {
27				f[i] = -1;
28				continue;
29			}
30			f[i] = f[q[hd]] + 1;
31			while (hd < tl && (f[i] < f[q[tl - 1]] || (f[i] == f[q[tl - 1]] && i + k[i] >= q[tl - 1] + k[q[tl - 1]])))
32				-- tl;
33			q[tl ++] = i;
34		}
35	}
36	
37	int main() {
38	#ifndef ONLINE_JUDGE
39		freopen("in.txt", "r", stdin);
40	#endif
41	
42		scanf("%d%d", &m, &q);
43		memset(k, 0, sizeof(k));
44		for (int i = 0; i < m; ++ i)
45			scanf("%d", p + i);
46		n = 0;
47		for (int i = 0; i < q; ++ i) {
48			scanf("%d", v + i);
49			if (v[i] > n)
50				n = v[i];
51		}
52		pre(n);
53		for (int i = 0; i < q; ++ i)
54			if (f[v[i]] == -1)
55				puts("oo");
56			else
57				printf("%d\n", f[v[i]]);
58	}
59	

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter