結果

問題 No.603 hel__world (2)
ユーザー pekempeypekempey
提出日時 2017-12-03 14:48:25
言語 C++14
(gcc 13.2.0 + boost 1.83.0)
結果
AC  
実行時間 2,762 ms / 3,000 ms
コード長 5,022 bytes
コンパイル時間 1,999 ms
コンパイル使用メモリ 107,184 KB
実行使用メモリ 34,832 KB
最終ジャッジ日時 2023-08-20 17:26:02
合計ジャッジ時間 11,164 ms
ジャッジサーバーID
(参考情報)
judge14 / judge13
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 38 ms
26,856 KB
testcase_01 AC 38 ms
26,884 KB
testcase_02 AC 37 ms
26,820 KB
testcase_03 AC 41 ms
26,888 KB
testcase_04 AC 42 ms
26,804 KB
testcase_05 AC 41 ms
26,812 KB
testcase_06 AC 34 ms
26,792 KB
testcase_07 AC 48 ms
26,856 KB
testcase_08 AC 35 ms
26,792 KB
testcase_09 AC 36 ms
26,892 KB
testcase_10 AC 43 ms
26,884 KB
testcase_11 AC 85 ms
33,252 KB
testcase_12 AC 71 ms
33,608 KB
testcase_13 AC 84 ms
33,252 KB
testcase_14 AC 35 ms
26,908 KB
testcase_15 AC 36 ms
26,816 KB
testcase_16 AC 38 ms
26,948 KB
testcase_17 AC 37 ms
26,788 KB
testcase_18 AC 36 ms
26,856 KB
testcase_19 AC 36 ms
26,792 KB
testcase_20 AC 2,762 ms
28,548 KB
testcase_21 AC 2,758 ms
28,604 KB
testcase_22 AC 34 ms
26,792 KB
testcase_23 AC 68 ms
26,788 KB
testcase_24 AC 75 ms
26,940 KB
testcase_25 AC 254 ms
33,320 KB
testcase_26 AC 249 ms
33,572 KB
testcase_27 AC 252 ms
33,344 KB
testcase_28 AC 72 ms
34,832 KB
testcase_29 AC 60 ms
28,552 KB
testcase_30 AC 49 ms
27,508 KB
testcase_31 AC 37 ms
26,788 KB
testcase_32 AC 57 ms
28,596 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#pragma GCC optimize ("O3")
#pragma GCC target ("avx")
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <string>
#include <ctime>
#include <map>

using namespace std;

typedef __int128 i128;

const int N = 10;
const int NN = 3;
const int M = 180;
const i128 B = 4 * i128(1e9) * i128(1e9);

const long long mod = 1e6 + 3;

long long fact[mod];
long long ifact[mod];
long long inv[mod];

long long modpow(long long a, long long b) {
  long long ret = 1;
  while (b > 0) {
    if (b & 1) ret = ret * a % mod;
    a = a * a % mod;
    b >>= 1;
  }
  return ret;
}

struct F {
  // base 10^20
  // a[0] . a[1]a[2] ... a[N-1]
  i128 a[N];

  i128 &operator[](int k) {
    return a[k];
  }
};

F operator+(F a, F b) {
  i128 c = 0;
  for (int i = N-1; i >= 0; i--) {
    a[i] += b[i] + c;
    if (a[i] > B) {
      a[i] -= B;
      c = 1;
    } else {
      c = 0;
    }
  }
  return a;
}

bool operator==(F a, F b) {
  for (int i = 0; i < N - NN; i++) {
    if (a[i] != b[i]) return false;
  }
  return true;
}

bool operator<(F a, F b) {
  for (int i = 0; i < N - NN; i++) {
    if (a[i] != b[i]) return a[i] < b[i];
  }
  return false;
}

bool operator>(F a, F b) {
  for (int i = 0; i < N - NN; i++) {
    if (a[i] != b[i]) return a[i] > b[i];
  }
  return false;
}

bool operator>=(F a, F b) {
  for (int i = 0; i < N - NN; i++) {
    if (a[i] != b[i]) return a[i] > b[i];
  }
  return true;
}

F half(F a) {
  i128 c = 0;
  for (int i = 0; i < N; i++) {
    a[i] += c * B;
    c = a[i] % 2;
    a[i] /= 2;
  }
  return a;
}

F from_int(i128 n) {
  F a = {};
  a[0] = n;
  return a;
}

F from_ratio(i128 a, i128 b) {
  F ret = {};
  ret[0] = a;
  i128 c = 0;
  for (int i = 0; i < N; i++) {
    ret[i] += c * B;
    c = ret[i] % b;
    ret[i] /= b;
  }
  return ret;
}

void print(i128 a) {
  if (a == 0) {
    printf("0");
    return;
  }
  char buf[100];
  int ptr = 0;
  while (a > 0) {
    buf[ptr++] = a % 10 + '0';
    a /= 10;
  }
  for (int i = ptr - 1; i >= 0; i--) {
    putchar(buf[i]);
  }
}

void print_fix(i128 a, int d) {
  char buf[100];
  int ptr = 0;
  for (int i = 0; i < d; i++) {
    buf[ptr++] = a % 10 + '0';
    a /= 10;
  }
  for (int i = ptr - 1; i >= 0; i--) {
    putchar(buf[i]);
  }
}

void show(F a) {
  print(a[0]);
  putchar('.');
  for (int i = 1; i < 5; i++) {
    putchar(' ');
    print_fix(a[i], 27);
  }
  printf("\n");
}

long long can_take(long long a, F b) {
  long long ok = 0;
  long long ng = 2e18;
  while (ng - ok > 1) {
    long long mid = (ok + ng) / 2;
    if (from_ratio(a + mid, mid) >= b) {
      ok = mid;
    } else {
      ng = mid;
    }
  }
  return ok;
}

long long C(int n, int r) {
  if (n < r) return 0;
  return fact[n] * ifact[r] % mod * ifact[n - r] % mod;
}

long long lucas(long long n, long long r) {
  if (n == 0 && r == 0) return 1;
  return C(n % mod, r % mod) * lucas(n / mod, r / mod) % mod;
}

int main() {
  fact[0] = 1;
  fact[1] = 1;
  ifact[0] = 1;
  ifact[1] = 1;
  inv[1] = 1;
  for (int i = 2; i < mod; i++) {
    fact[i] = fact[i - 1] * i % mod;
    inv[i] = inv[mod % i] * (mod - mod / i) % mod;
    ifact[i] = ifact[i - 1] * inv[i] % mod;
  }

  vector<long long> cnt(26);
  for (int i = 0; i < 26; i++) {
    cin >> cnt[i];  
  }
  string s;
  cin >> s;
  vector<int> sum(26);
  for (char c : s) {
    sum[c - 'a']++;
  }
  for (int i = 0; i < 26; i++) {
    if (sum[i] > cnt[i]) {
      cout << 0 << endl;
      return 0;
    }
    cnt[i] -= sum[i];
  }
  vector<vector<int>> g(26);
  int i = 0;
  while (i < s.size()) {
    int j = i;
    while (i < s.size() && s[i] == s[j]) {
      i++;
    }
    g[s[j] - 'a'].push_back(i - j);
  }

  long long ans = 1;
  for (int iii = 0; iii < 26; iii++) {
    auto x = g[iii];
    long long C = cnt[iii];
    F ok = from_int(1);
    F ng = from_int(2e18);
    if (C == 0) continue;
    clock_t beg = clock();

    map<int, int> xs;
    for (int e : x) xs[e]++;

    for (int ii = 0; ii < M; ii++) {
      F mid = half(ok + ng);

      // x[0]/1 (x[0]+1)/2 (x[0]+2)/3 ... 
      // (x + k) / k >= mid
      
      i128 t = 0;
      for (auto kv : xs) {
        t += can_take(kv.first, mid) * kv.second;
      }
      if (t >= C) {
        ok = mid;
      } else {
        ng = mid;
      }
    }
    struct Foo {
      int x;
      long long take;
      long long cnt;
    };
    vector<Foo> take, take2;
    for (auto kv : xs) {
      long long t = can_take(kv.first, ng);
      take.push_back({kv.first, t, kv.second});
      C -= t * kv.second;
    }
    for (Foo foo : take) {
      if (can_take(foo.x, ok) > can_take(foo.x, ng)) {
        long long canuse = min(C, foo.cnt);
        Foo bar = foo;
        foo.take++;
        foo.cnt = canuse;
        bar.cnt -= canuse;
        take2.push_back(foo);
        take2.push_back(bar);
        C -= canuse;
      } else {
        take2.push_back(foo);
      }
    }
    for (Foo foo : take2) {
      ans *= modpow(lucas(foo.x + foo.take, foo.take), foo.cnt);
      ans %= mod;
    }
  }

  cout << ans << endl;
}

0