[BZOJ2790][Poi2012]Distance

2790: [Poi2012]Distance

Time Limit: 40 Sec  Memory Limit: 128 MB
Submit: 225  Solved: 115
[Submit][Status][Discuss]

Description

 

 

对于两个正整数a、b,这样定义函数d(a,b):每次操作可以选择一个质数p,将a变成a*p或a/p,

如果选择变成a/p就要保证p是a的约数,d(a,b)表示将a变成b所需的最少操作次数。例如d(69,42)=3。

现在给出n个正整数A1,A2,...,An,对于每个i (1<=i<=n),求最小的j(1<=j<=n)使得i≠j且d(Ai,Aj)最小。

 

 

 

Input

第一行一个正整数n (2<=n<=100,000)。第二行n个正整数A1,A2,...,An (Ai<=1,000,000)。

 

 

 

Output

输出n行,依次表示答案。

 

 

 

Sample Input

6
1
2
3
4
5
6

Sample Output

2
1
1
2
1
2

HINT

 

Source

[Submit][Status][Discuss]

很容易推出来 $d(x,y)=g(x)+g(y)-2*g(\gcd(x,y))$ 其中g(x)表示x是几个质数的乘积

$g$函数只需要一个线性筛就能求出来,对于$a_i$,$g(a_i)$是固定的,重点在于最小化$g(y)-2*g(gcd(x,y))$

可以枚举$a_i$的因子$x$,用$f[x]$表示是$x$的倍数的$a[j]$使得$g[a[j]]$最小的数

因为要求$i≠j$,所以得维护最小值和次小值,时间复杂度$O(n\sqrt m+m)$ $m=\max{a_i}$

PS:今天BZOJ居然卡住了,管理员今天不在吗?

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 #define N 100010
 6 #define M 1000010
 7 int prime[M],tot,g[M];
 8 inline void pre(int t)
 9 {
10     g[0]=1e9;
11     for(int i=2;i<=t;i++)
12     {
13         if(!g[i])prime[++tot]=i,g[i]=1;
14         for(int j=1;j<=tot&&i*prime[j]<=t;j++)
15         {
16             g[i*prime[j]]=g[i]+1;
17             if(!(i%prime[j]))break;
18         }
19     }
20 }
21 int n,a[N],f[M][2],maxn;
22 inline void update(int x,int i)
23 {
24     if(g[a[x]]<=g[a[f[i][0]]])
25     f[i][1]=f[i][0],f[i][0]=x;
26     else if(g[a[x]]<=g[a[f[i][1]]])
27     f[i][1]=x;
28 }
29 int main()
30 {
31     scanf("%d",&n);
32     for(int i=1;i<=n;i++)
33     scanf("%d",&a[i]),maxn=max(a[i],maxn);
34     pre(maxn);
35     for(int i=n;i;i--)
36     {
37         for(int j=1;j*j<=a[i];j++)
38         if(!(a[i]%j))
39         {
40             update(i,j);
41             if(j*j!=a[i])
42             update(i,a[i]/j);
43         }
44     }
45     for(int i=1;i<=n;i++)
46     {
47         int ans=1e9,tmp=1e9;
48         for(int j=1;j*j<=a[i];j++)
49         if(!(a[i]%j))
50         {
51             int k=j,x;
52             if(f[k][0]!=i)x=f[k][0];
53             else x=f[k][1];
54             int t=g[a[x]]-2*g[k];
55             if(t<ans||(t==ans&&x<tmp))
56             ans=t,tmp=x;
57             k=a[i]/j;            
58             if(f[k][0]!=i)x=f[k][0];
59             else x=f[k][1];
60             t=g[a[x]]-2*g[k];
61             if(t<ans||(t==ans&&x<tmp))
62             ans=t,tmp=x;
63         }
64         printf("%d\n",tmp);
65     }
66 }
View Code

 

posted @ 2016-02-14 10:04  xuruifan  阅读(749)  评论(3编辑  收藏  举报