题目: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 #include2 #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 }