zoukankan      html  css  js  c++  java
  • BZOJ2790: [Poi2012]Distance

    2790: [Poi2012]Distance

    Time Limit: 40 Sec  Memory Limit: 128 MB
    Submit: 158  Solved: 83
    [Submit][Status]

    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

    题解:
    WA了n发终于过了这道题。。。坑点多多啊。。。
    首先我们要推出d(x,y)=g[x]+g[y]-2*g[gcd(x,y)]
    这是很好推的。
    然后我们对于每一个i,gcd(i,?)是可以枚举的,另f[i]表示x%i==0,且g[x]最小的数,然后我们需要最小化g[gcd(i,?)],
    这样我们可以枚举每个数的约数j,更新f[j]即可。最后再扫一遍。因为要i!=j,所以还要保留次大。
    坑点:sqrt(a[i])不能算两次。最小的j满足d(a[i],a[j])最小。。。
    代码:
      1 #include<cstdio>
      2 
      3 #include<cstdlib>
      4 
      5 #include<cmath>
      6 
      7 #include<cstring>
      8 
      9 #include<algorithm>
     10 
     11 #include<iostream>
     12 
     13 #include<vector>
     14 
     15 #include<map>
     16 
     17 #include<set>
     18 
     19 #include<queue>
     20 
     21 #include<string>
     22 
     23 #define inf 1000000000
     24 
     25 #define maxn 1000000+5
     26 
     27 #define maxm 500+100
     28 
     29 #define eps 1e-10
     30 
     31 #define ll long long
     32 
     33 #define pa pair<int,int>
     34 
     35 #define for0(i,n) for(int i=0;i<=(n);i++)
     36 
     37 #define for1(i,n) for(int i=1;i<=(n);i++)
     38 
     39 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
     40 
     41 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
     42 
     43 #define mod 1000000007
     44 
     45 using namespace std;
     46 
     47 inline int read()
     48 
     49 {
     50 
     51     int x=0,f=1;char ch=getchar();
     52 
     53     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     54 
     55     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
     56 
     57     return x*f;
     58 
     59 }
     60 int n,tot,a[maxn],p[maxn],f[maxn][2],g[maxn+1];
     61 
     62 int main()
     63 
     64 {
     65 
     66     freopen("input.txt","r",stdin);
     67 
     68     freopen("output.txt","w",stdout);
     69     for2(i,2,maxn)
     70     {
     71         if(!g[i])p[++tot]=i,g[i]=1;
     72         for1(j,tot)
     73         {
     74             int k=i*p[j];
     75             if(k>maxn)break;
     76             g[k]=g[i]+1;
     77             if(i%p[j]==0)break;
     78         }
     79     }
     80     g[0]=inf;
     81 
     82     n=read();
     83     for1(i,n)a[i]=read();
     84     for3(i,n,1)
     85     {
     86         int x=sqrt(a[i]);
     87         for1(j,x)if(a[i]%j==0)
     88         {
     89             int k=j;
     90             if(g[a[f[k][0]]]>=g[a[i]])f[k][1]=f[k][0],f[k][0]=i;
     91             else if(g[a[f[k][1]]]>=g[a[i]])f[k][1]=i;
     92             if(j*j==a[i])break;
     93             k=a[i]/j;
     94             if(g[a[f[k][0]]]>=g[a[i]])f[k][1]=f[k][0],f[k][0]=i;
     95             else if(g[a[f[k][1]]]>=g[a[i]])f[k][1]=i;
     96         }
     97     }
     98     for1(i,n)
     99     {
    100         int x=sqrt(a[i]),tmp=inf>>1,ans=n+1;
    101         for1(j,x)if(a[i]%j==0)
    102         {
    103             int k=j;
    104             if(f[k][0]!=i)
    105             {
    106                 int t=g[a[i]]-2*g[k]+g[a[f[k][0]]];
    107                 if(t<tmp||(t==tmp&&f[k][0]<ans))tmp=t,ans=f[k][0];
    108             }
    109             else
    110             {
    111                 int t=g[a[i]]-2*g[k]+g[a[f[k][1]]];
    112                 if(t<tmp||(t==tmp&&f[k][1]<ans))tmp=t,ans=f[k][1];
    113             }
    114             k=a[i]/j;
    115             if(f[k][0]!=i)
    116             {
    117                 int t=g[a[i]]-2*g[k]+g[a[f[k][0]]];
    118                 if(t<tmp||(t==tmp&&f[k][0]<ans))tmp=t,ans=f[k][0];
    119             }
    120             else
    121             {
    122                 int t=g[a[i]]-2*g[k]+g[a[f[k][1]]];
    123                 if(t<tmp||(t==tmp&&f[k][1]<ans))tmp=t,ans=f[k][1];
    124             }
    125         }
    126         printf("%d
    ",ans);
    127     }
    128 
    129     return 0;
    130 
    131 } 
    View Code

     貌似有关gcd的问题枚举约数是个不错的选择?

  • 相关阅读:
    2018年Q1增长最快的20个技能
    微信备份方法
    [转] 浅谈 OpenResty
    Angular默认路由策略-PathLocationStrategy策略页面刷新报404错误解决方案
    [转] ABP框架Web API跨域问题的解决方案
    [转] Win10插入U盘后双击无法打开,无法访问,显示设备未就绪;驱动哥帮你解决
    java jdk 8u191 官网下载地址
    IDEA 2019 注册码
    [JAVA] maven 阿里云节点 settings.xml
    .net webapi跨域 web.config配置
  • 原文地址:https://www.cnblogs.com/zyfzyf/p/4119348.html
Copyright © 2011-2022 走看看