QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#631331#8691. Square Root Partitioninghos_lyricWA 29ms21864kbC++1412.0kb2024-10-12 00:45:542024-10-12 00:45:55

Judging History

你现在查看的是最新测评结果

  • [2024-10-12 00:45:55]
  • 评测
  • 测评结果:WA
  • 用时:29ms
  • 内存:21864kb
  • [2024-10-12 00:45:54]
  • 提交

answer

#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <functional>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

using namespace std;

// using Int = long long;

template <class T1, class T2> ostream &operator<<(ostream &os, const pair<T1, T2> &a) { return os << "(" << a.first << ", " << a.second << ")"; };
template <class T> ostream &operator<<(ostream &os, const vector<T> &as) { const int sz = as.size(); os << "["; for (int i = 0; i < sz; ++i) { if (i >= 256) { os << ", ..."; break; } if (i > 0) { os << ", "; } os << as[i]; } return os << "]"; }
template <class T> void pv(T a, T b) { for (T i = a; i != b; ++i) cerr << *i << " "; cerr << endl; }
template <class T> bool chmin(T &t, const T &f) { if (t > f) { t = f; return true; } return false; }
template <class T> bool chmax(T &t, const T &f) { if (t < f) { t = f; return true; } return false; }
#define COLOR(s) ("\x1b[" s "m")


#ifndef LIBRA_OTHER_INT128_H_
#define LIBRA_OTHER_INT128_H_

#include <stdio.h>
#include <iostream>

constexpr unsigned __int128 toUInt128(const char *s) {
  unsigned __int128 x = 0;
  for (; *s; ++s) x = x * 10 + (*s - '0');
  return x;
}
constexpr __int128 toInt128(const char *s) {
  if (*s == '-') return -toInt128(s + 1);
  __int128 x = 0;
  for (; *s; ++s) x = x * 10 + (*s - '0');
  return x;
}
unsigned __int128 inUInt128() {
  static char buf[41];
  scanf("%s", buf);
  return toUInt128(buf);
}
__int128 inInt128() {
  static char buf[41];
  scanf("%s", buf);
  return toInt128(buf);
}

void out(unsigned __int128 x) {
  static char buf[41];
  int len = 0;
  do { buf[len++] = '0' + static_cast<int>(x % 10); } while (x /= 10);
  for (int i = len; --i >= 0; ) putchar(buf[i]);
}
void out(__int128 x) {
  if (x < 0) {
    putchar('-');
    out(-static_cast<unsigned __int128>(x));
  } else {
    out(static_cast<unsigned __int128>(x));
  }
}
std::ostream &operator<<(std::ostream &os, unsigned __int128 x) {
  static char buf[41];
  int len = 0;
  do { buf[len++] = '0' + static_cast<int>(x % 10); } while (x /= 10);
  for (int i = len; --i >= 0; ) os << buf[i];
  return os;
}
std::ostream &operator<<(std::ostream &os, __int128 x) {
  if (x < 0) {
    os << '-' << -static_cast<unsigned __int128>(x);
  } else {
    os << static_cast<unsigned __int128>(x);
  }
  return os;
}

#endif  // LIBRA_OTHER_INT128_H_


////////////////////////////////////////////////////////////////////////////////
// floor(a b / 2^128)
inline unsigned __int128 mul128High(unsigned __int128 a, unsigned __int128 b) {
  const unsigned __int128 a0 = static_cast<unsigned long long>(a), a1 = a >> 64;
  const unsigned __int128 b0 = static_cast<unsigned long long>(b), b1 = b >> 64;
  return ((((a0 * b0) >> 64) + static_cast<unsigned long long>(a0 * b1) + static_cast<unsigned long long>(a1 * b0)) >> 64) + ((a0 * b1) >> 64) + ((a1 * b0) >> 64) + a1 * b1;
}

// Hold y := (2^128 x) mod M
template <int ID> struct RMModInt128 {
  static unsigned __int128 M;
  static unsigned __int128 INV_M;  // M^-1 mod 2^128
  static unsigned __int128 TWO256;  // 2^256 mod M
  static void setM(unsigned __int128 m) {
    assert(m & 1); assert(1 <= m); assert(!(m >> 127));
    M = m;
    INV_M = (3 * M) ^ 2;
    for (int i = 0; i < 5; ++i) INV_M *= (2 - M * INV_M);
    TWO256 = (-M) % M;
    for (int i = 0; i < 128; ++i) TWO256 = ((TWO256 <<= 1) >= M) ? (TWO256 - M) : TWO256;
  }
  // (2^-128 a) mod M  (0 <= a < 2^128 m)
  static inline unsigned __int128 reduce(unsigned __int128 a) {
    const unsigned __int128 c = -mul128High(INV_M * a, M);
    return (c >= M) ? (c + M) : c;
  }
  // (2^-128 a b) mod M  (0 <= a b < 2^128 m)
  static inline unsigned __int128 mulReduce(unsigned __int128 a, unsigned __int128 b) {
    const unsigned __int128 c = mul128High(a, b) - mul128High(INV_M * (a * b), M);
    return (c >= M) ? (c + M) : c;
  }

  unsigned __int128 y;
  RMModInt128() : y(0U) {}
  RMModInt128(unsigned x_) : y(mulReduce(TWO256, x_ % M)) {}
  RMModInt128(unsigned long long x_) : y(mulReduce(TWO256, x_ % M)) {}
  RMModInt128(unsigned __int128 x_) : y(mulReduce(TWO256, x_ % M)) {}
  RMModInt128(int x_) : y(mulReduce(TWO256, ((x_ %= static_cast<__int128>(M)) < 0) ? (x_ + static_cast<__int128>(M)) : x_)) {}
  RMModInt128(long long x_) : y(mulReduce(TWO256, ((x_ %= static_cast<__int128>(M)) < 0) ? (x_ + static_cast<__int128>(M)) : x_)) {}
  RMModInt128(__int128 x_) : y(mulReduce(TWO256, ((x_ %= static_cast<__int128>(M)) < 0) ? (x_ + static_cast<__int128>(M)) : x_)) {}
  unsigned __int128 get() const { return reduce(y); }
  RMModInt128 &operator+=(const RMModInt128 &a) { y = ((y += a.y) >= M) ? (y - M) : y; return *this; }
  RMModInt128 &operator-=(const RMModInt128 &a) { y = ((y -= a.y) >= M) ? (y + M) : y; return *this; }
  RMModInt128 &operator*=(const RMModInt128 &a) { y = mulReduce(y, a.y); return *this; }
  RMModInt128 &operator/=(const RMModInt128 &a) { return (*this *= a.inv()); }
  template <class T> RMModInt128 pow(T e) const {
    if (e < 0) return inv().pow(-e);
    for (RMModInt128 a = *this, b = 1U; ; a *= a) { if (e & 1) { b *= a; } if (!(e >>= 1)) { return b; } }
  }
  RMModInt128 inv() const {
    unsigned __int128 a = M, b = reduce(reduce(y)); __int128 u = 0, v = 1;
    for (; b; ) { const unsigned __int128 q = a / b; const unsigned __int128 c = a - q * b; a = b; b = c; const __int128 w = u - static_cast<__int128>(q) * v; u = v; v = w; }
    assert(a == 1U); RMModInt128 r; r.y = u; r.y = (r.y >= M) ? (r.y + M) : r.y; return r;
  }
  RMModInt128 operator+() const { return *this; }
  RMModInt128 operator-() const { RMModInt128 a; a.y = y ? (M - y) : 0U; return a; }
  RMModInt128 operator+(const RMModInt128 &a) const { return (RMModInt128(*this) += a); }
  RMModInt128 operator-(const RMModInt128 &a) const { return (RMModInt128(*this) -= a); }
  RMModInt128 operator*(const RMModInt128 &a) const { return (RMModInt128(*this) *= a); }
  RMModInt128 operator/(const RMModInt128 &a) const { return (RMModInt128(*this) /= a); }
  template <class T> friend RMModInt128 operator+(T a, const RMModInt128 &b) { return (RMModInt128(a) += b); }
  template <class T> friend RMModInt128 operator-(T a, const RMModInt128 &b) { return (RMModInt128(a) -= b); }
  template <class T> friend RMModInt128 operator*(T a, const RMModInt128 &b) { return (RMModInt128(a) *= b); }
  template <class T> friend RMModInt128 operator/(T a, const RMModInt128 &b) { return (RMModInt128(a) /= b); }
  explicit operator bool() const { return y; }
  bool operator==(const RMModInt128 &a) const { return (y == a.y); }
  bool operator!=(const RMModInt128 &a) const { return (y != a.y); }
  // !
  bool operator<(const RMModInt128 &a) const { return (y < a.y); }
  friend std::ostream &operator<<(std::ostream &os, const RMModInt128 &a) { return os << a.get(); }
};
template <int ID> unsigned __int128 RMModInt128<ID>::M;
template <int ID> unsigned __int128 RMModInt128<ID>::INV_M;
template <int ID> unsigned __int128 RMModInt128<ID>::TWO256;
////////////////////////////////////////////////////////////////////////////////


using RMM128ForPrime = RMModInt128<-20220617>;

template <class T> vector<T> merge(const vector<T> &a, const vector<T> &b) {
  vector<T> c(a.size() + b.size());
  std::merge(a.begin(), a.end(), b.begin(), b.end(), c.begin());
  return c;
}

int bsf128(__int128 a) {
  const long long a64 = a;
  return a64 ? __builtin_ctzll(a64) : (64 + __builtin_ctzll(a >> 64));
}
__int128 gcd128(__int128 a, __int128 b) {
  if (a < 0) a = -a;
  if (b < 0) b = -b;
  if (a == 0) return b;
  if (b == 0) return a;
  const int s = bsf128(a | b);
  a >>= bsf128(a);
  do {
    b >>= bsf128(b);
    if (a > b) swap(a, b);
    b -= a;
  } while (b);
  return a << s;
}

// Checks if n is a prime using Miller-Rabin test
bool isPrime128(__int128 n) {
  if (n <= 1 || !(n & 1)) return (n == 2);
  RMM128ForPrime::setM(n);
  const int s = bsf128(n - 1);
  const __int128 d = (n - 1) >> s;
  // Based on conjectures in Zhang, Two kinds of strong pseudoprimes up to 10^36.
  for (const __int128 base : {2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
                              31, 37, 41, 43, 47, 53, 59, 61, 67, 71}) {
    if (base >= n) continue;
    RMM128ForPrime a = RMM128ForPrime(base).pow(d);
    if (a.get() == 1 || static_cast<__int128>(a.get()) == n - 1) continue;
    bool ok = false;
    for (int i = 0; i < s - 1; ++i) {
      if (static_cast<__int128>((a *= a).get()) == n - 1) {
        ok = true;
        break;
      }
    }
    if (!ok) return false;
  }
  return true;
}


#include <chrono>
#ifdef LOCAL
mt19937_64 rng(58);
#else
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
#endif

using INT = __int128;
using Mint = RMModInt128<0>;

using Pair = pair<Mint, Mint>;
Pair operator+(const Pair &a, const Pair &b) { return make_pair(a.first + b.first, a.second + b.second); }
Pair operator-(const Pair &a, const Pair &b) { return make_pair(a.first - b.first, a.second - b.second); }
// Pair operator*(const Pair &a, const Pair &b) { return make_pair(a.first * b.first, a.first * b.second + a.second * b.first); }
Pair operator*(const Pair &a, Mint k) { return make_pair(a.first * k, a.second * k); }
Pair operator*(Mint k, const Pair &a) { return make_pair(k * a.first, k * a.second); }
Pair &operator+=(Pair &a, const Pair &b) { return a = a + b; }
Pair &operator-=(Pair &a, const Pair &b) { return a = a - b; }
// Pair &operator*=(Pair &a, const Pair &b) { return a = a * b; }
Pair &operator*=(Pair &a, Mint k) { return a = a * k; }
// constexpr Pair ZERO(0, 0);


INT rng127() {
  return (INT)rng() << 63 ^ rng();
}

INT M;
bool isNonResidue(Mint a) {
  return (a && a.pow((M - 1) / 2) != 1);
}

// (b + sqrt(b^2 - a))^((p+1)/2) in F_p(sqrt(b^2 - a))
Mint modSqrt(Mint a) {
  Mint b, d;
  for (; ; ) {
    b = rng127();
    d = b * b - a;
    if (isNonResidue(d)) break;
  }
  Mint f0 = b, f1 = 1, g0 = 1, g1 = 0, tmp;
  for (INT e = (M + 1) >> 1; e; e >>= 1) {
    if (e & 1) {
      tmp = (g0 * f0 + d * ((g1 * f1) )) ;
      g1 = (g0 * f1 + g1 * f0) ;
      g0 = tmp;
    }
    tmp = (f0 * f0 + d * ((f1 * f1) )) ;
    f1 = (2 * f0 * f1) ;
    f0 = tmp;
  }
  assert(g0 * g0 == a);
  return g0;
}

int N;
char A[40][100'010];

int main() {
  for (; ; ) {
    M = ((INT)1<<125) + (rng127() >> 2);
    if (isPrime128(M)) break;
  }
  Mint::setM(M);
  
  // fixed non-residue
  Mint R;
  for (; ; ) {
    R = rng127();
    if (isNonResidue(R)) break;
  }
cerr<<"M = "<<M<<", R = "<<R<<endl;
  
  for (; ~scanf("%d", &N); ) {
    for (int i = 0; i < N; ++i) {
      scanf("%s", A[i]);
    }
    
    vector<Pair> fs(1 << (N/2)), gs(1 << (N - N/2));
    fs[0] = gs[0] = Pair(0, 0);
    for (int i = 0; i < N; ++i) {
      Mint b = 0;
      for (char *a = A[i]; *a; ++a) (b *= 10) += (*a - '0');
      Pair c(0, 0);
      if (isNonResidue(b)) {
        c.second = modSqrt(R * b);
      } else {
        c.first = modSqrt(b);
      }
cerr<<b<<": "<<c<<endl;
      if (i < N/2) {
        for (int h = 0; h < 1 << i; ++h) {
          fs[h | 1 << i] = fs[h] - c;
          fs[h] -= c;
        }
      } else {
        for (int h = 0; h < 1 << (i - N/2); ++h) {
          gs[h | 1 << (i - N/2)] = gs[h] - c;
          gs[h] += c;
        }
      }
    }
    
    sort(fs.begin(), fs.end());
    sort(gs.begin(), gs.end());
    long long ans = 0;
    for (int x = 0, yL = 0, yR = 0; x < (int)fs.size(); ++x) {
      for (; yL < (int)gs.size() && gs[yL] <  fs[x]; ++yL) {}
      for (; yR < (int)gs.size() && gs[yR] <= fs[x]; ++yR) {}
      ans += (yR - yL);
    }
    assert(ans % 2 == 0);
    ans /= 2;
    printf("%lld\n", ans);
  }
  return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 1ms
memory: 3836kb

input:

3
2 2 8

output:

1

result:

ok 1 number(s): "1"

Test #2:

score: 0
Accepted
time: 1ms
memory: 5956kb

input:

4
4 9 25 49

output:

0

result:

ok 1 number(s): "0"

Test #3:

score: -100
Wrong Answer
time: 29ms
memory: 21864kb

input:

36
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

output:

2433220608

result:

wrong answer 1st numbers differ - expected: '4537567650', found: '2433220608'