結果
| 問題 | No.3416 マッチ棒パズル Extra |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2025-12-23 23:55:18 |
| 言語 | Text (cat 8.3) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 5,532 bytes |
| 記録 | |
| コンパイル時間 | 258 ms |
| コンパイル使用メモリ | 8,104 KB |
| 実行使用メモリ | 7,852 KB |
| 最終ジャッジ日時 | 2025-12-23 23:55:19 |
| 合計ジャッジ時間 | 1,554 ms |
|
ジャッジサーバーID (参考情報) |
judge4 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | WA * 26 |
ソースコード
// bagutteru ue ni osoi...
#include "template/template.hpp"
//
#include "math/stern-brocot-tree.hpp"
//
#include "modint/montgomery-modint.hpp"
#include "modulo/binomial.hpp"
//
using namespace Nyaan;
using mint = LazyMontgomeryModInt<998244353>;
// using mint = LazyMontgomeryModInt<1000000007>;
using vm = vector<mint>;
using vvm = vector<vm>;
mint naive(ll N) {
mint ans = 0;
rep1(H, N) {
ll x = (2 * N + 1) / (2 * H + 1);
if (x < 3) break;
ans += (x - 1) / 2;
}
return ans;
}
mint calc(ll N) {
// (-2x+1)(2y+1)>=2N+2
auto inside = [&](i128 x, i128 y) -> bool {
return (-2 * x + 1) * (2 * y + 1) >= 2 * N + 2;
};
i128 xl = -(N + 1), yl = 0, xr = 0;
/*
auto candicate = [&](i128 x, i128 y, i128 c, i128 d) {
i128 a = x * d - y * c;
// (-2x+1)(2y+1)=2N+2
// xd-yc=a
// (-2x+1)(2yc+c)=c(2N+2)
// (-2x+1)(2(xd-a)+c)=c(2N+2)
// (-2x+1)(2dx+(c-2a))=c(2N+2)
i128 A = -2 * 2 * d;
i128 B = -2 * (c - 2 * a) + 2 * d;
long double x_dst = -1.0l * B / (2 * A);
i128 res = max<i128>(1, (x_dst - x) / c + 0.5);
trc(x, y, c, d, res);
return res;
};
*/
using Int = i128;
vector<pair<Int, Int>> cv;
{
using ld = long double;
// inside かつ x <= xr
auto f = [&](Int x, Int y) { return x <= xr && inside(x, y); };
// (a, b) から (c, d) 方向に進めるだけ進む
auto go_naive = [&](Int a, Int b, Int c, Int d) -> Int {
assert(f(a, b));
Int r = 1, s = 0;
while (f(a + r * c, b + r * d)) r *= 2;
while ((r /= 2) != 0) {
if (f(a + r * c, b + r * d)) s += r, a += r * c, b += r * d;
}
return s;
};
auto go = [&](Int a, Int b, Int c, Int d) -> Int {
assert(f(a, b));
// trc("go1", a, b, c, d);
if (c == 0) {
assert(d == -1);
assert(!f(a + c, b + d));
return 0;
}
i128 rhs = a * d - b * c;
// (-2x+1)(2y+1)=2N+2
// xd-yc=r
// (-2x+1)(2yc+c)=c(2N+2)
// (-2x+1)(2(xd-r)+c)=c(2N+2)
// (-2x+1)(2dx+(c-2r))=c(2N+2)
i128 A = -2 * 2 * d;
i128 B = -2 * (c - 2 * rhs) + 2 * d;
i128 C = c - 2 * rhs - c * (2 * N + 2);
ld sqrtD = sqrtl(ld(B) * B - 4.0l * A * C);
if (isnan(sqrtD)) sqrtD = 0;
if (A == 0) trc(a, b, c, d, A, B, C);
ld x1 = A != 0 ? (-B - sqrtD) / (2 * A) : -1.0l * C / B;
i128 s = max<i128>(0, (min<ld>(xr, x1) - a) / c + 0.5l);
trc(s);
while (!f(a + s * c, b + s * d)) s--;
while (f(a + (s + 1) * c, b + (s + 1) * d)) s++;
trc("go1", a, b, c, d, s);
assert(go_naive(a, b, c, d) == s);
return s;
};
// (a, b) が out, (a + c * k, b + d * k) が in とする
// out の間進めるだけ進む
// 無限に進めるときは -1
auto go2 = [&](Int a, Int b, Int c, Int d) -> Int {
assert(!f(a, b) and !f(a + c, b + d));
if (c == 0) {
assert(d == 1);
// (-2x+1)(2y+1)=2N+2
Int q = ((2 * N + 2) / (-2 * a + 1) - 1) / 2;
while ((-2 * a + 1) * (2 * q + 1) < 2 * N + 2) q++;
trc("go2", a, b, c, d, q);
return (q - b) - 1;
}
i128 rhs = a * d - b * c;
// (-2x+1)(2y+1)=2N+2
// xd-yc=a
// (-2x+1)(2yc+c)=c(2N+2)
// (-2x+1)(2(xd-a)+c)=c(2N+2)
// (-2x+1)(2dx+(c-2a))=c(2N+2)
i128 A = -2 * 2 * d;
i128 B = -2 * (c - 2 * rhs) + 2 * d;
i128 C = c - 2 * rhs - c * (2 * N + 2);
ld sqrtD = sqrtl(ld(B) * B - 4.0l * A * C);
if (isnan(sqrtD)) sqrtD = 0;
ld x0 = A == 0 ? (-B + sqrtD) / (2 * A) : -C / B;
i128 s = max<i128>(0, (min<i128>(xr, x0) - a) / c + 0.5l);
trc("go2", a, b, c, d, s);
if (s - 1 > 0 and !f(a + (s - 1) * c, b + (s - 1) * d)) return s - 2;
if (s - 0 > 0 and !f(a + (s - 0) * c, b + (s - 0) * d)) return s - 1;
if (s + 1 > 0 and !f(a + (s + 1) * c, b + (s + 1) * d)) return s - 0;
if (s + 2 > 0 and !f(a + (s + 2) * c, b + (s + 2) * d)) return s + 1;
if (s + 3 > 0 and !f(a + (s + 3) * c, b + (s + 3) * d)) return s + 2;
return -1;
};
Int x = xl, y = yl;
assert(f(x, y) and go(x, y, 0, -1) == 0);
cv.emplace_back(x, y);
SternBrocotTreeNode<Int> sb;
while (x < xr) {
Int a, b;
if (f(x + 1, y)) {
a = 1, b = 0;
} else {
while (!f(x + sb.lx, y + sb.ly)) {
assert(!sb.seq.empty());
Int bc = sb.seq.back();
sb.go_parent(bc < 0 ? -bc : bc);
}
while (true) {
assert(f(x + sb.lx, y + sb.ly));
assert(!f(x + sb.rx, y + sb.ry));
if (f(x + sb.lx + sb.rx, y + sb.ly + sb.ry)) {
Int s = go(x + sb.lx, y + sb.ly, sb.rx, sb.ry);
assert(s > 0);
sb.go_right(s);
} else {
Int t = go2(x + sb.rx, y + sb.ry, sb.lx, sb.ly);
if (t <= 0) {
a = sb.lx, b = sb.ly;
break;
} else {
sb.go_left(t);
}
}
}
}
Int s = go(x, y, a, b);
x += a * s, y += b * s;
cv.emplace_back(x, y);
}
}
mint ans = 0;
Binomial<mint> C;
rep(i, sz(cv) - 1) {
ll y = cv[i].se;
ll dx = cv[i + 1].fi - cv[i].fi;
ll dy = cv[i + 1].se - cv[i].se;
ll g = gcd(dx, dy);
mint cur = (mint{dx + 1} * (dy + 1) - (g + 1)) * C.inv(2) - dx - dy;
cur += mint{dx} * y;
ans += cur;
}
return ans + 1;
}
void q() {
inl(N);
out(calc(N));
}
void Nyaan::solve() {
int t = 1;
in(t);
while (t--) q();
}