数值距离
题目描述
我们可以对一个数进行两种操作,即把一个数乘上一个质数或者除以一个质
数。我们定义两个数 a,b 之间的距离为把 a 变成 b 需要执行的最少操作次数,例
如 d(69,42)=3,因为 42=69/23*2*7。
我们给出一个长度为 n 的序列 a 1 ,a 2 ,...,a n ,对于每一个 a i 我们需要找到一个
不等于 i 的最小的 j 使得 a i 和 a j 的距离是最小的。
输入格式
第一行一个整数 n。
接下来 n 行,第 i 行一个整数 a i 。
输出格式
n 行,第 i 行一个整数,表示 d(ai,aj)最小时最小的 j。
输入样例
6
1
2
3
4
5
6
输出样例
2
1
1
2
1
2
数据规模
30%的数据,n<=1000。
另外 20%的数据,a i <=1000。
100%的数据,2<=n<=100000,1<=a i <=1000000。
我们看到ai<=1000000,正常情况下,如果复杂度与a没关系应该是10^9
考虑以ai为点建图,如果两个数可以通过一次变换就建边
用ai做起点,如果ai为起点的路径碰上了以aj为起点的路径,那么就要更新ai和aj的答案
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 using namespace std; 8 typedef long long lol; 9 lol n; 10 lol vis[1000001],v[1000001],dist[1000001],tot,Min[1000001],pos[1000001],a[1000001],pre[1000001],prime[1000001]; 11 void zyys(int x,int y) 12 { 13 if (v[x]==v[y]) return; 14 int now=dist[x]+dist[y]+1; 15 if (Min[v[x]]==now) pos[v[x]]=min(pos[v[x]],v[y]); 16 if (Min[v[y]]==now) pos[v[y]]=min(pos[v[y]],v[x]); 17 if (Min[v[x]]>now) Min[v[x]]=now,pos[v[x]]=v[y]; 18 if (Min[v[y]]>now) Min[v[y]]=now,pos[v[y]]=v[x]; 19 if (dist[x]==dist[y]+1) 20 v[x]=min(v[x],v[y]); 21 } 22 void SPFA() 23 { 24 int i; 25 queue<int>Q; 26 memset(dist,127/2,sizeof(dist)); 27 for (i=1; i<=n; i++) 28 { 29 if (v[a[i]]==i) Q.push(a[i]); 30 } 31 while (Q.empty()==0) 32 { 33 int u=Q.front(); 34 Q.pop(); 35 int b=u; 36 while (b!=1) 37 { 38 int now=u/pre[b]; 39 if (v[now]==0) v[now]=v[u],dist[now]=dist[u]+1,Q.push(now); 40 else zyys(now,u); 41 b/=pre[b]; 42 } 43 for (i=1; i<=tot&&1ll*u*prime[i]<=1000000; i++) 44 { 45 int now=u*prime[i]; 46 if (v[now]==0) v[now]=v[u],dist[now]=dist[u]+1,Q.push(now); 47 else zyys(now,u); 48 } 49 } 50 } 51 int main() 52 { 53 lol i,j,d,ans; 56 cin>>n; 57 vis[1]=1; 58 for (i=2; i<=1000000; i++) 59 { 60 if (vis[i]==0) 61 { 62 ++tot; 63 prime[tot]=i; 64 pre[i]=i; 65 } 66 for (j=1; j<=tot; j++) 67 { 68 if (1ll*i*prime[j]>1000000) break; 69 vis[i*prime[j]]=1; 70 pre[i*prime[j]]=prime[j]; 71 if (i%prime[j]==0) break; 72 } 73 } 74 memset(Min,127/2,sizeof(Min)); 75 memset(pos,127/2,sizeof(pos)); 76 for (i=1; i<=n; i++) 77 { 78 scanf("%lld",&a[i]); 79 if (v[a[i]]==0) v[a[i]]=i; 80 else 81 { 82 Min[i]=Min[v[a[i]]]=0; 83 pos[i]=min(pos[i],v[a[i]]); 84 pos[v[a[i]]]=min(pos[v[a[i]]],i); 85 } 86 } 87 SPFA(); 88 for (i=1; i<=n; i++) 89 printf("%lld\n",pos[i]); 90 }