結果
| 問題 | No.5020 Averaging | 
| コンテスト | |
| ユーザー |  siman | 
| 提出日時 | 2024-02-25 13:40:52 | 
| 言語 | C++23 (gcc 13.3.0 + boost 1.87.0) | 
| 結果 | 
                                AC
                                 
                             | 
| 実行時間 | 955 ms / 1,000 ms | 
| コード長 | 4,509 bytes | 
| コンパイル時間 | 1,609 ms | 
| コンパイル使用メモリ | 145,308 KB | 
| 実行使用メモリ | 6,676 KB | 
| スコア | 14,749,563 | 
| 最終ジャッジ日時 | 2024-02-25 13:41:44 | 
| 合計ジャッジ時間 | 51,991 ms | 
| ジャッジサーバーID (参考情報) | judge11 / judge15 | 
| 純コード判定しない問題か言語 | 
(要ログイン)
| ファイルパターン | 結果 | 
|---|---|
| other | AC * 50 | 
ソースコード
#include <cassert>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <climits>
#include <map>
#include <queue>
#include <set>
#include <cstring>
#include <vector>
#include <random>
#include <chrono>
using namespace std;
typedef long long ll;
constexpr int N = 45;
constexpr int T = 50;
constexpr double TIME_LIMIT = 0.95;
constexpr ll
BASE_SCORE = 500000000000000000;
ll A[N];
ll B[N];
ll A_copy[N];
ll B_copy[N];
class Xorshift {
public:
  Xorshift(uint64_t seed = 88675123) {
    _x = 123456789;
    _y = 362436069;
    _z = 521288629;
    _w = seed;
    for (int i = 0; i < 100; ++i) {
      next();
    }
  }
  uint64_t next(uint64_t a, uint64_t b) {
    return a + (next() % (b - a + 1));
  }
  uint64_t next() {
    uint64_t t = _x ^ (_x << 11);
    _x = _y;
    _y = _z;
    _z = _w;
    _w = (_w ^ (_w >> 19)) ^ (t ^ (t >> 8));
    return _w;
  }
  double random_double() {
    return static_cast<double>(next()) / UINT64_MAX;
  }
  double random_double(double a, double b) {
    return a + (b - a) * random_double();
  }
private:
  uint64_t _x, _y, _z, _w;
};
class Timer {
public:
  Timer() {
    begin();
    _duration = 0.0;
  }
  void begin() {
    _start_at = chrono::system_clock::now();
  }
  double get_time() {
    chrono::system_clock::time_point end_at = chrono::system_clock::now();
    _duration = chrono::duration_cast<std::chrono::nanoseconds>(end_at - _start_at).count();
    return _duration / 1000000000.0;
  }
  double progress(double time_limit) {
    return get_time() / time_limit;
  }
private:
  chrono::system_clock::time_point _start_at;
  double _duration;
};
Xorshift g_rng;
class Solver {
public:
  void run() {
    load_data();
    setup();
    auto res = sa();
    /*
    cout << N << endl;
    for (int i = 0; i < N; ++i) {
      cout << A[i] << " " << B[i] << endl;
    }
     */
    cout << res.size() << endl;
    for (int i = 0; i < T; ++i) {
      cout << res[i].first << " " << res[i].second << endl;
    }
  }
private:
  void load_data() {
    int _N;
    cin >> _N;
    for (int i = 0; i < N; ++i) {
      cin >> A[i] >> B[i];
    }
  }
  void setup() {
  }
  vector <pair<int, int>> sa(double time_limit = TIME_LIMIT) {
    Timer timer;
    int U[T], V[T];
    for (int i = 0; i < T; ++i) {
      int u, v;
      do {
        u = g_rng.next(0, N - 1);
        v = g_rng.next(0, N - 1);
      } while (u == v);
      U[i] = u;
      V[i] = v;
    }
    int best_U[T], best_V[T];
    memcpy(best_U, U, sizeof(U));
    memcpy(best_V, V, sizeof(V));
    int cur_score = calc_score_full(U, V);
    int best_score = cur_score;
    double cur_time = timer.get_time();
    double total_diff = 0.0;
    double t = 0.1;
    ll R = 100000000;
    int try_count = 0;
    while (cur_time < time_limit) {
      cur_time = timer.get_time();
      double remain_time = (time_limit - cur_time) / time_limit;
      int score = calc_score_full(U, V);
      double diff_score = cur_score - score;
      total_diff += fabs(diff_score);
      if (diff_score > 0 || (g_rng.next() % R < R * exp(diff_score / (t * pow(remain_time, 2))))) {
        cur_score = score;
        if (best_score < score) {
          best_score = score;
          memcpy(best_U, U, sizeof(U));
          memcpy(best_V, V, sizeof(V));
        }
      } else {
      }
      ++try_count;
      double average_diff = total_diff / try_count;
      t = 0.25 * remain_time * average_diff;
    }
    fprintf(stderr, "try_count: %d, best_score: %d\n", try_count, best_score);
    vector <pair<int, int>> res;
    for (int i = 0; i < T; ++i) {
      res.emplace_back(make_pair(best_U[i] + 1, best_V[i] + 1));
    }
    return res;
  }
  int calc_score_full(int *U, int *V) {
    memcpy(A_copy, A, sizeof(A));
    memcpy(B_copy, B, sizeof(B));
    for (int i = 0; i < N; ++i) {
      int u = U[i];
      int v = V[i];
      ll sum_a = A_copy[u] + A_copy[v];
      ll sum_b = B_copy[u] + B_copy[v];
      A_copy[u] = sum_a >> 1;
      A_copy[v] = sum_a >> 1;
      B_copy[u] = sum_b >> 1;
      B_copy[v] = sum_b >> 1;
    }
    ll diff_A = abs(BASE_SCORE - A_copy[0]);
    ll diff_B = abs(BASE_SCORE - B_copy[0]);
    ll max_diff = max(diff_A, diff_B);
    // Score = (int)(2000000.0 - 100000.0 * math.log10(1.0 * max(ErrorA, ErrorB) + 1.0))
    int score = (int) (2000000.0 - 100000.0 * log10(1.0 * max_diff + 1.0));
    return score;
  }
};
int main() {
  std::cin.tie(0)->sync_with_stdio(0);
  Solver solver;
  solver.run();
  return 0;
}
            
            
            
        