[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

鸣谢 oimaster

[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 }

时间: 2024-10-21 01:34:36

[BZOJ2790][Poi2012]Distance的相关文章

洛谷P3533 [POI2012]RAN-Rendezvous

P3533 [POI2012]RAN-Rendezvous 题目描述 Byteasar is a ranger who works in the Arrow Cave - a famous rendezvous destination among lovers. The cave consists of nn chambers connected with one-way corridors. In each chamber exactly one outgoing corridor is ma

461.求两个数字转成二进制后的“汉明距离” Hamming Distance

public class Solution { public int HammingDistance(int x, int y) { int distance = 0; string sX = Convert.ToString(x, 2); string sY = Convert.ToString(y, 2); int maxLength = Math.Max(sX.Length, sY.Length); //填充0,使两个字符串右对齐 sX = sX.PadLeft(maxLength, '0

LeetCode 72 Edit Distance

Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2. (each operation is counted as 1 step.) You have the following 3 operations permitted on a word: a) Insert a character b) Delete a character c) Repla

461. Hamming Distance

The Hamming distance between two integers is the number of positions at which the corresponding bits are different. Given two integers x and y, calculate the Hamming distance. Note:0 ≤ x, y < 2^31. Example: Input: x = 1, y = 4 Output: 2 Explanation:

搬土距离(Earth Mover&#39;s Distance)

搬土距离(The Earth Mover's Distance,EMD)最早由Y. Rubner在1999年的文章<A Metric for Distributions with Applications to Image Databases>中提出,它是归一化的从一个分布变为另一个分布的最小代价,因此可用于表征两个分布之间的距离. 例如,对于图像而言,它可以看做是由色调.饱和度.亮度三个分量组成,每个分量的直方图就是一个分布.不同的图像对应的直方图不同,因此图像之间的距离可以用直方图的距离表

Bzoj 2789: [Poi2012]Letters 树状数组,逆序对

2789: [Poi2012]Letters Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 278  Solved: 185[Submit][Status][Discuss] Description 给出两个长度相同且由大写英文字母组成的字符串A.B,保证A和B中每种字母出现的次数相同. 现在每次可以交换A中相邻两个字符,求最少需要交换多少次可以使得A变成B. Input 第一行一个正整数n (2<=n<=1,000,000),表示字符串的长度

distance.c

1 #include "stdio.h" 2 #include "string.h" 3 #include "math.h" 4 #include "malloc.h" 5 6 const long long Max_size = 2000;//输入字符串的最大长度,可以由单个词条和多个词条组成 7 const long long N = 40;//输出与某个单词最接近的N个词 8 const long long Max_w

[Locked] One Edit Distance

One Edit Distance Given two strings S and T, determine if they are both one edit distance apart. 分析: 编辑距离复杂度为O(MN),而本题显然不能用这么高的复杂度:首先,可以通过判断两个字符串是否等长来决定用增一位.减一位.替换一位这三种方法之一来使得两个字符串等同,如果都不行,就return false:然后同时遍历S和T,第一次遇到不匹配的,就用刚才判断出的方法拯救一下:第二次还遇到不匹配的,就

[BZOJ2797][Poi2012]Squarks

2797: [Poi2012]Squarks Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 211  Solved: 89[Submit][Status][Discuss] Description 设有n个互不相同的正整数{X1,X2,...Xn},任取两个Xi,Xj(i≠j),能算出Xi+Xj.现在所有取法共n*(n-1)/2个和,要你求出X1,X2,...Xn. Input 第一行一个正整数n (3<=n<=300).第二行n*(n-1)/2