[Poi2012]Distance

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2790

解题报告:
总的来说题目不是太难
首先可以发现: 设G[x]代表x包含多少个质数(可以相同,比如G[4] = 2),对于d(x, y) = G[x] + G[y] - 2 * G[gcd(x, y)];
可以发现,对于枚举的数字x,我们可以把gcd()看成自变量,可以发现自变量个数就是x的约数。
那么算法就显而易见了,
把二元函数d(x, y) --> f(x, gcd(x, ?)) = G[x] + G[?] - 2 * G[gcd(x, ?)] 在这里,x,gcd(x, ?)都是可以枚举的,而?就是变量
显然可以发现,对于每个gcd(x, ?)计一个最小的(G[?] - 2 * G[gcd(x, ?)])即可,
我们就可以做到O(N * 根号1000000),由于根号项是每个数的约数,实际上远没有这么多,所以可以AC
有一点要注意,由于i!=j,则对于每个gcd()要计最大,次大值

代码:

  1 #include 
  2 #include 
  3 #include 
  4 using namespace std;
  5 
  6 const int MAXN = 110000, MaxVal = 1000000;
  7 int G[MaxVal + 10], deg[MaxVal + 10], v1[MaxVal + 10], p1[MaxVal + 10], v2[MaxVal + 10], p2[MaxVal + 10];
  8 int N, A[MAXN], nowval;
  9 
 10 struct node
 11 {
 12     int v, num;
 13 }block[MAXN];
 14 int len;
 15 
 16 void Init()
 17 {
 18     scanf("%d", &N);
 19     for(int i = 1;i <= N;i++)
 20         scanf("%d", &A[i]);
 21     for(int i = 1;i <= MaxVal;i++)
 22         deg[i] = i;
 23     for(int i = 2;i <= MaxVal;i++)
 24     if (deg[i] == i)
 25     {
 26         for(int j = i + i;j <= MaxVal;j += i)
 27             deg[j] = min(deg[j], i);
 28     }
 29     G[1] = 0;
 30     for(int i = 2;i <= MaxVal;i++)
 31     {
 32         G[i] = G[i / deg[i]] + 1;
 33     }
 34 }
 35 
 36 void Dfs(int dep, int v)
 37 {
 38     if (dep == len + 1)
 39     {
 40         int tv = G[block[0].v] - 2 * G[v];
 41         if (tv < v1[v])
 42         {
 43             v2[v] = v1[v];
 44             p2[v] = p1[v];
 45             v1[v] = tv;
 46             p1[v] = block[0].num;
 47         }
 48         else
 49         if (tv < v2[v])
 50         {
 51             v2[v] = tv;
 52             p2[v] = block[0].num;
 53         }
 54         return ;
 55     }
 56     int tmp = 1;
 57     for(int i = 0;i <= block[dep].num;i++)
 58     {
 59         Dfs(dep + 1, v * tmp);
 60         tmp *= block[dep].v;
 61     }
 62 }
 63 
 64 int Ans, Anspos;
 65 
 66 void Dfs2(int dep, int v)
 67 {
 68     if (dep == len + 1)
 69     {
 70         if (p1[v] != block[0].num)
 71         {
 72             if (v1[v] < Ans || v1[v] == Ans && p1[v] < Anspos)
 73                 Ans = v1[v], Anspos = p1[v];
 74         }
 75         else
 76         {
 77             if (v2[v] < Ans || v2[v] == Ans && p2[v] < Anspos)
 78                 Ans = v2[v], Anspos = p2[v];
 79         }
 80         return ;
 81     }
 82     int tmp = 1;
 83     for(int i = 0;i <= block[dep].num;i++)
 84     {
 85         Dfs2(dep + 1, v * tmp);
 86         tmp *= block[dep].v;
 87     }
 88 }
 89 
 90 void Work()
 91 {
 92     for(int i = 1;i <= MaxVal;i++)
 93         v1[i] = v2[i] = 10000000;
 94     for(int i = 1;i <= N;i++)
 95     {
 96         len = 0;
 97         block[0] = (node){A[i], i};
 98         int x = A[i];
 99         while(x != 1)
100         {
101             if (deg[x] != block[len].v || len == 0)
102             {
103                 block[++len] = (node){deg[x], 1};
104             }
105             else
106             {
107                 block[len].num++;
108             }
109             x /= deg[x];
110         }
111         Dfs(1, 1);
112     }
113     for(int i = 1;i <= N;i++)
114     {
115         len = 0;
116         block[0] = (node){A[i], i};
117         int x = A[i];
118         while(x != 1)
119         {
120             if (deg[x] != block[len].v || len == 0)
121             {
122                 block[++len] = (node){deg[x], 1};
123             }
124             else
125             {
126                 block[len].num++;
127             }
128             x /= deg[x];
129         }
130         Ans = 100000000;
131         Dfs2(1, 1);
132         printf("%d\n", Anspos);
133     }
134 }
135 
136 int main()
137 {
138     freopen("input.txt","r",stdin);
139     freopen("output.txt","w",stdout);
140     Init();
141     Work();
142     return 0;
143 }

转载于:https://www.cnblogs.com/lwhbbs/archive/2012/05/26/2519426.html

你可能感兴趣的:([Poi2012]Distance)