fork download
  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. typedef long long ll;
  6. typedef pair<int, int> ii;
  7.  
  8. const int INF = 1e9;
  9. const ll LINF = 1e18;
  10.  
  11. template<typename T>
  12. void minimize(T& a, const T& b) {
  13. if (b < a) a = b;
  14. }
  15.  
  16. // - Nhận xét 1: Với mọi i, ta luôn có thể chọn b(i) = 1 (vì gcd(1, x) = 1, với mọi x)
  17. // Do đó, trong phương án tối ưu, với mọi i, ta có:
  18. // |b(i) - a(i)| <= a(i) - 1
  19. // => b(i) <= 2 * a(i) - 1
  20. // => max({b(i)}) <= 2 * max({a(i)}) - 1 <= 59
  21. // - Nhận xét 2: Với mọi (i, j), để gcd(b(i), b(j)) = 1 thì b(i) và b(j) không được có chung thừa số nguyên tố nào.
  22. // - Từ 2 nhận xét trên, ta rút ra được lời giải hoàn chỉnh như sau:
  23. // max({b(i)}) <= 59 => Chỉ có 17 số nguyên tố <= 59
  24. // => mask biểu diễn các số nguyên tố đã xuất hiện
  25. // => dp[i][mask] = Giá trị nhỏ nhất của biểu thức khi xét b[1..i],
  26. // với mask biểu diễn các số nguyên tố đã xuất hiện trong b[1..i]
  27. const int N = 1e2 + 5;
  28.  
  29. int prime[17] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59};
  30. int n;
  31. int a[N];
  32.  
  33. int prime_mask[60]; // prime_mask[x] = mask biểu diễn các thừa số nguyên tố của x
  34. int dp[N][1 << 17]; // dp[i][mask]
  35. int b[N];
  36.  
  37. int main() {
  38. ios::sync_with_stdio(false);
  39. cin.tie(nullptr);
  40. cin >> n;
  41. for (int i = 1; i <= n; i++) cin >> a[i];
  42.  
  43. for (int x = 1; x <= 59; x++) {
  44. for (int i = 0; i < 17; i++) {
  45. if (x % prime[i] == 0) prime_mask[x] |= (1 << i);
  46. }
  47. }
  48.  
  49. for (int i = 0; i <= n; i++) {
  50. for (int mask = 0; mask < (1 << 17); mask++) {
  51. int& cur = dp[i][mask];
  52. cur = INF;
  53. if (i == 0) {
  54. if (mask == 0) cur = 0;
  55. continue;
  56. }
  57. for (int x = 1; x <= 59; x++) {
  58. if ((mask & prime_mask[x]) == prime_mask[x]) { // prime_mask[x] là submask của mask
  59. int prev_mask = mask ^ prime_mask[x];
  60. minimize(cur, dp[i - 1][prev_mask] + abs(x - a[i]));
  61. }
  62. }
  63. }
  64. }
  65.  
  66. int best_mask = 0;
  67. for (int mask = 0; mask < (1 << 17); mask++) {
  68. if (dp[n][mask] < dp[n][best_mask]) best_mask = mask;
  69. }
  70.  
  71. for (int i = n; i >= 1; i--) {
  72. for (int x = 1; x <= 59; x++) {
  73. if ((best_mask & prime_mask[x]) == prime_mask[x]) { // prime_mask[x] là submask của best_mask
  74. int prev_mask = best_mask ^ prime_mask[x];
  75. if (dp[i - 1][prev_mask] + abs(x - a[i]) == dp[i][best_mask]) {
  76. b[i] = x;
  77. best_mask = prev_mask;
  78. break;
  79. }
  80. }
  81. }
  82. }
  83.  
  84. for (int i = 1; i <= n; i++) cout << b[i] << ' ';
  85. }
  86.  
Success #stdin #stdout 0.13s 8124KB
stdin
5
1 1 1 1 1
stdout
1 1 1 1 1