码迷,mamicode.com
首页 > 其他好文 > 详细

[BZOJ 2790] [POI 2012] Distance

时间:2017-09-13 22:14:39      阅读:189      评论:0      收藏:0      [点我收藏+]

标签:表示   include   print   using   emc   mem   names   条件   长度   

题意

  给定长度为 n 的序列 a[1], a[2], ..., a[n] .

  对于每个数 i , 求出 j , 满足 dist(a[i], a[j]) 最小, 且 i != j .

  dist(x, y) 表示由 x 变为 y 的最小步数, 每次变换可以乘上素数 p , 或除以素数 p .

  2 <= n <= 100000 , 1 <= a[i] <= 1000000 .

 

分析

  从前往后扫一遍, 从后往前扫一遍, 来满足 i != j 的条件.

  记 Min[i] 表示访问到点 i 的最小步数, 通过枚举质因子, 维护 Min[i] 并更新答案.

 

实现

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cctype>
 5 #include <algorithm>
 6 using namespace std;
 7 #define F(i, a, b) for (register int i = (a); i <= (b); i++)
 8 #define D(i, a, b) for (register int i = (a); i >= (b); i--)
 9 inline int rd(void) {
10     int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == -) f = -1;
11     int x = 0; for (; isdigit(c); c = getchar()) x = x*10+c-0; return x*f;
12 }
13 inline void gmin(pair<int, int> &x, pair<int, int> y) { x = min(x, y); }
14 
15 const int N = 100005;
16 const int M = 1000000;
17 const int INF = ~0u>>2;
18 
19 bool v[M+5]; int pri[M+5], tot, cnt[M+5];
20 int n, a[N];
21 pair<int, int> Min[M+5], ans[N], tmp[N];
22 
23 void Oper(int i) {
24     for (int x = 1; x * x <= a[i]; x++) if (a[i] % x == 0) {
25         if (Min[x] != make_pair(INF, -1))
26             gmin(ans[i], make_pair(Min[x].first + cnt[a[i] / x], Min[x].second));
27         if (Min[a[i] / x] != make_pair(INF, -1))
28             gmin(ans[i], make_pair(Min[a[i] / x].first + cnt[x], Min[a[i] / x].second));
29     }
30     for (int x = 1; x * x <= a[i]; x++) if (a[i] % x == 0) {
31         gmin(Min[x], make_pair(cnt[a[i] / x] , i));
32         gmin(Min[a[i] / x], make_pair(cnt[x], i));
33     }
34 }
35 
36 int main(void) {
37     #ifndef ONLINE_JUDGE
38         freopen("bzoj2790.in", "r", stdin);
39     #endif
40     
41     v[1] = true;
42     F(i, 2, M) {
43         if (!v[i]) pri[++tot] = i, cnt[i] = 1;
44         for (int j = 1; j <= tot && i * pri[j] <= M; j++) {
45             v[i * pri[j]] = true, cnt[i * pri[j]] = cnt[i] + 1;
46             if (i % pri[j] == 0) break;
47         }
48     }
49     
50     n = rd();
51     F(i, 1, n) a[i] = rd();
52 
53     F(i, 1, n) ans[i] = make_pair(INF, -1);
54     F(i, 1, M) Min[i] = make_pair(INF, -1);
55     F(i, 1, n)
56         Oper(i);
57     
58     memcpy(tmp, ans, sizeof ans);
59     F(i, 1, n) ans[i] = make_pair(INF, -1);
60     F(i, 1, M) Min[i] = make_pair(INF, -1);
61     D(i, n, 1)
62         Oper(i);
63     
64     F(i, 1, n) printf("%d\n", min(tmp[i], ans[i]).second);
65     
66     return 0;
67 }

 

[BZOJ 2790] [POI 2012] Distance

标签:表示   include   print   using   emc   mem   names   条件   长度   

原文地址:http://www.cnblogs.com/Sdchr/p/7517734.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!