QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#120141 | #6188. Elliptic Curve Problem | hos_lyric | AC ✓ | 2126ms | 5880kb | C++14 | 6.6kb | 2023-07-06 14:12:52 | 2023-07-06 14:13:02 |
Judging History
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;
/*
-(a, b): out
-(c, d): in
*/
struct Info {
INT a, b, c, d;
};
Info stack[1'000'010];
// \sum[0<x<=(P-1)/2] floor((x^2 + A) / P)
INT solve(INT P, INT A) {
// cerr<<"solve "<<P<<" "<<A<<endl;
// above
auto inside = [&](INT x, INT y) -> bool {
return (x >= 0 && P * y > x * x + A);
};
// max k s.t. (x - k u, y - k v): in
auto maxIn = [&](INT x, INT y, INT u, INT v) -> INT {
assert(inside(x, y));
if (u == 0) {
assert(v == 1);
return y - ((x * x + A) / P) - 1;
}
// in, out
auto check = [&](INT k) -> bool {
return inside(x - k * u, y - k * v);
};
INT lo = 0, hi = 1;
for (; check(hi); ) {
lo = hi;
hi <<= 1;
}
for (; lo + 1 < hi; ) {
const INT mid = (lo + hi) / 2;
(check(mid) ? lo : hi) = mid;
}
return lo;
};
INT x = (P - 1) / 2;
INT y = (x*x + A) / P + 1;
int top = 0;
stack[top] = Info{0, 1, 1, 0};
INT ans = 0;
for (; x > 0; ) {
// cerr<<"x = "<<x<<", y = "<<y<<endl;
bool side;
for (; ; ) {
const auto &f = stack[top];
// cerr<<" f = ("<<f.a<<", "<<f.b<<") ("<<f.c<<", "<<f.d<<")"<<endl;
if (!inside(x - f.a, y - f.b) && inside(x - f.c, y - f.d)) {
side = inside(x - (f.a + f.c), y - (f.b + f.d));
break;
} else {
--top;
}
}
for (; ; side = !side) {
const auto &f = stack[top];
// cerr<<" f = "<<f.a<<" "<<f.b<<" "<<f.c<<" "<<f.d<<", side = "<<side<<endl;
if (side) {
const INT k = maxIn(x - f.c, y - f.d, f.a, f.b);
stack[++top] = Info{f.a, f.b, k * f.a + f.c, k * f.b + f.d};
} else {
/*
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 - f.a) * f.c - P * f.d;
const INT denom = 2 * f.c * f.c;
// cerr<<" jiku = "<<numer<<"/"<<denom<<endl;
INT q = numer / denom, r = numer % denom;
if (r < 0) {
--q;
r += denom;
}
if (2 * r > denom) {
++q;
r -= denom;
}
auto check = [&](INT k) -> bool {
const INT xx = x - (f.a + k * f.c);
const INT yy = y - (f.b + k * f.d);
return inside(xx, yy);
};
// out, in
INT lo = 1, hi = min(q, (x - f.a) / f.c);
// cerr<<" q = "<<q<<", hi = "<<hi<<", check(hi) = "<<check(hi)<<endl;
if (check(hi)) {
const INT lim = hi;
hi = 2;
for (; !check(hi); ) {
lo = hi;
hi <<= 1;
if (hi >= lim) {
hi = lim;
break;
}
}
for (; lo + 1 < hi; ) {
const INT mid = (lo + hi) / 2;
(check(mid) ? hi : lo) = mid;
}
const INT k = lo;
stack[++top] = Info{f.a + k * f.c, f.b + k * f.d, f.c, f.d};
} else {
// convex hull slope
const INT u = f.c, v = f.d;
const INT k = maxIn(x, y, u, v);
const INT xx = x - k * u;
const INT yy = y - k * v;
// cerr<<" (u, v) = ("<<u<<", "<<v<<"), k = "<<k<<endl;
ans += ((x - xx + 1) * (y + yy + 1) - (k + 1)) / 2 - (x - xx + 1) - (yy - 1);
x = xx;
y = yy;
break;
}
}
}
}
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: 0ms
memory: 3584kb
input:
11 3 8
output:
3
result:
ok 1 number(s): "3"
Test #2:
score: 0
Accepted
time: 100ms
memory: 3660kb
input:
998244353 11451400 919810000
output:
454174074
result:
ok 1 number(s): "454174074"
Test #3:
score: 0
Accepted
time: 2079ms
memory: 3796kb
input:
96311898227 25437319919 55129361817
output:
14846091352
result:
ok 1 number(s): "14846091352"
Test #4:
score: 0
Accepted
time: 2032ms
memory: 3780kb
input:
93361455259 23166562299 23393760915
output:
113606479
result:
ok 1 number(s): "113606479"
Test #5:
score: 0
Accepted
time: 2060ms
memory: 3864kb
input:
95670332497 15858139735 18812394512
output:
1477133816
result:
ok 1 number(s): "1477133816"
Test #6:
score: 0
Accepted
time: 2058ms
memory: 3844kb
input:
94221254297 78612110347 90331192055
output:
5859602618
result:
ok 1 number(s): "5859602618"
Test #7:
score: 0
Accepted
time: 2022ms
memory: 3940kb
input:
92756073587 18915851957 32881684894
output:
6982950261
result:
ok 1 number(s): "6982950261"
Test #8:
score: 0
Accepted
time: 2032ms
memory: 5880kb
input:
93651628361 3508055978 32362767220
output:
14427310592
result:
ok 1 number(s): "14427310592"
Test #9:
score: 0
Accepted
time: 2090ms
memory: 3836kb
input:
97506758381 48269906857 58513759044
output:
5121898347
result:
ok 1 number(s): "5121898347"
Test #10:
score: 0
Accepted
time: 2125ms
memory: 3816kb
input:
99954950231 20710324571 44996152988
output:
12142951150
result:
ok 1 number(s): "12142951150"
Test #11:
score: 0
Accepted
time: 2118ms
memory: 3836kb
input:
99367158071 38747300608 85189731653
output:
23221174712
result:
ok 1 number(s): "23221174712"
Test #12:
score: 0
Accepted
time: 2126ms
memory: 3792kb
input:
99936206351 6721710119 93710740278
output:
43494512281
result:
ok 1 number(s): "43494512281"