QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#120140#6188. Elliptic Curve Problemhos_lyricAC ✓1738ms87396kbC++145.0kb2023-07-06 14:12:392023-07-06 14:12:42

Judging History

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

  • [2023-08-10 23:21:45]
  • System Update: QOJ starts to keep a history of the judgings of all the submissions.
  • [2023-07-06 14:12:42]
  • 评测
  • 测评结果:AC
  • 用时:1738ms
  • 内存:87396kb
  • [2023-07-06 14:12:39]
  • 提交

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 <map>
#include <numeric>
#include <queue>
#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; }

#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_


using INT = __int128;

INT P, A;
INT X, Y;
INT ans;

// above
inline bool inside(INT x, INT y) {
  return (P * y > x*x + A);
}

// next slope: (a/b, c/d]
void dfs(INT a, INT b, INT c, INT d) {
// cerr<<"dfs "<<a<<" "<<b<<" "<<c<<" "<<d<<endl;
  {
    /*
      \exists? k s.t. -(a + k c, b + k d): in
      P (Y - (b + k d)) > (X - (a + k c))^2 + A
      c^2 k^2 - (2 (X - a) c - P d) k + * < 0
    */
    const INT numer = 2 * (X - a) * c - P * d;
    const INT denom = 2 * c * c;
    INT q = numer / denom, r = numer % denom;
    if (r < 0) {
      --q;
      r += denom;
    }
    if (2 * r > denom) {
      ++q;
      r -= denom;
    }
    const INT k = q;
    if (!inside(X - (a + k * c), Y - (b + k * d))) {
      return;
    }
  }
  const INT e = a + c;
  const INT f = b + d;
  if (inside(X - e, Y - f)) {
    dfs(a, b, e, f);
  }
  if (inside(X - e, Y - f)) {
    /*
      max k s.t. -(k e, k f): in
    */
    auto check = [&](INT k) -> bool {
      return inside(X - k * e, Y - k * f);
    };
    INT lo = 1, hi = 2;
    for (; check(hi); ) {
      lo = hi;
      hi <<= 1;
    }
    for (; lo + 1 < hi; ) {
      const INT mid = (lo + hi) / 2;
      (check(mid) ? lo : hi) = mid;
    }
    const INT k = lo;
    const INT XX = X - k * e;
    const INT YY = Y - k * f;
// cerr<<"  "<<k<<" ("<<e<<", "<<f<<"); ("<<X<<", "<<Y<<") -> ("<<XX<<", "<<YY<<")"<<endl;
    ans += ((X - XX + 1) * (Y + YY + 1) - (k + 1)) / 2 - (X - XX + 1) - (YY - 1);
    X = XX;
    Y = YY;
  }
  if (inside(X - c, X - d)) {
    dfs(e, f, c, d);
  }
}

// \sum[0<x<=(P-1)/2] floor((x^2 + A) / P)
INT solve(INT P_, INT A_) {
  P = P_;
  A = A_;
// cerr<<"solve "<<P<<" "<<A<<endl;
  X = (P - 1) / 2;
  Y = (X*X + A) / P + 1;
  ans = 0;
  dfs(0, 1, 1, 0);
  ans += X * (Y - 1);
  return ans;
}


void stress() {
  for (INT P = 3; P < 1000; P += 2) {
    for (INT A = 0; A <= P; ++A) {
      INT brt = 0;
      for (INT x = 1; x <= (P - 1) / 2; ++x) {
        brt += (x*x + A) / P;
      }
      const INT res = solve(P, A);
      if (brt != res) {
        cerr << P << " " << A << ": " << brt << " " << res << endl;
        assert(false);
      }
    }
  }
}

int main() {
  // stress();
  
  Int P, L, R;
  for (; ~scanf("%lld%lld%lld", &P, &L, &R); ) {
    INT ans = 0;
    ans += solve(P, P - L);
    ans -= solve(P, P - R - 1);
    cout << ans << endl;
  }
  return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

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

input:

11 3 8

output:

3

result:

ok 1 number(s): "3"

Test #2:

score: 0
Accepted
time: 83ms
memory: 9508kb

input:

998244353 11451400 919810000

output:

454174074

result:

ok 1 number(s): "454174074"

Test #3:

score: 0
Accepted
time: 1685ms
memory: 81036kb

input:

96311898227 25437319919 55129361817

output:

14846091352

result:

ok 1 number(s): "14846091352"

Test #4:

score: 0
Accepted
time: 1660ms
memory: 87396kb

input:

93361455259 23166562299 23393760915

output:

113606479

result:

ok 1 number(s): "113606479"

Test #5:

score: 0
Accepted
time: 1679ms
memory: 50928kb

input:

95670332497 15858139735 18812394512

output:

1477133816

result:

ok 1 number(s): "1477133816"

Test #6:

score: 0
Accepted
time: 1689ms
memory: 68336kb

input:

94221254297 78612110347 90331192055

output:

5859602618

result:

ok 1 number(s): "5859602618"

Test #7:

score: 0
Accepted
time: 1645ms
memory: 65792kb

input:

92756073587 18915851957 32881684894

output:

6982950261

result:

ok 1 number(s): "6982950261"

Test #8:

score: 0
Accepted
time: 1654ms
memory: 55008kb

input:

93651628361 3508055978 32362767220

output:

14427310592

result:

ok 1 number(s): "14427310592"

Test #9:

score: 0
Accepted
time: 1681ms
memory: 43704kb

input:

97506758381 48269906857 58513759044

output:

5121898347

result:

ok 1 number(s): "5121898347"

Test #10:

score: 0
Accepted
time: 1738ms
memory: 61104kb

input:

99954950231 20710324571 44996152988

output:

12142951150

result:

ok 1 number(s): "12142951150"

Test #11:

score: 0
Accepted
time: 1728ms
memory: 64984kb

input:

99367158071 38747300608 85189731653

output:

23221174712

result:

ok 1 number(s): "23221174712"

Test #12:

score: 0
Accepted
time: 1722ms
memory: 45344kb

input:

99936206351 6721710119 93710740278

output:

43494512281

result:

ok 1 number(s): "43494512281"