結果
| 問題 |
No.886 Direct
|
| コンテスト | |
| ユーザー |
Min_25
|
| 提出日時 | 2019-09-14 23:31:51 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 4,214 bytes |
| コンパイル時間 | 1,109 ms |
| コンパイル使用メモリ | 101,176 KB |
| 実行使用メモリ | 6,944 KB |
| 最終ジャッジ日時 | 2024-07-06 22:04:31 |
| 合計ジャッジ時間 | 2,413 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 WA * 1 |
| other | AC * 24 WA * 8 |
ソースコード
#include <cstdio>
#include <cassert>
#include <cmath>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <functional>
#include <stack>
#include <queue>
#include <tuple>
#define getchar getchar_unlocked
#define putchar putchar_unlocked
#define _rep(_1, _2, _3, _4, name, ...) name
#define rep2(i, n) rep3(i, 0, n)
#define rep3(i, a, b) rep4(i, a, b, 1)
#define rep4(i, a, b, c) for (int i = int(a); i < int(b); i += int(c))
#define rep(...) _rep(__VA_ARGS__, rep4, rep3, rep2, _)(__VA_ARGS__)
using namespace std;
using i64 = long long;
using u8 = unsigned char;
using u32 = unsigned;
using u64 = unsigned long long;
using u128 = __uint128_t;
using f80 = long double;
int get_int() {
int n, c, sign = 0;
while ((c = getchar()) < '-');
if (c == '-') sign = 1, n = 0;
else n = c - '0';
while ((c = getchar()) >= '0') n = n * 10 + c - '0';
return sign ? -n : n;
}
int isqrt(i64 N) {
return sqrtl(N);
}
template <typename T>
T fast_sum(i64 N, i64 M) {
if (N < M) swap(N, M);
if (M == 0) return T(N, M);
const int vN = isqrt(N), wN = max<int>(1, N / (vN + 1));
const int vM = max<int>(1, M / wN);
vector<T> lN(wN + 1);
vector<T> memo(vN + vM);
vector<int> offset(vN + 2, -2); int o = 0;
auto memoize = [&] (int n, int m, const T& v) {
if (m == 0) return;
if (offset[n] == -2) offset[n] = o - m;
memo[o++] = v;
};
auto cache = [&] (int n, int m) -> T {
return (m == 0) ? T(n, m) : memo[offset[n] + m];
};
vector<i64> qn(vN + 2), qm(vM + 2);
auto calc = [&] (const i64 n, const i64 m, const i64 k) -> T {
auto ret = T(n, m);
if (n <= 1 || m == 0) return ret;
const int vn = isqrt(n), wn = n / (vn + 1), vm = max<int>(1, m / wn);
for (int i = 1; i <= vn + 1; ++i) qn[i] = n / i;
for (int i = 1; i <= vm + 1; ++i) qm[i] = m / i;
for (int n2 = 1, m2 = m / n; n2 <= vn; ++n2) {
if (qm[m2 + 1] >= qn[n2 + 1]) {
ret -= cache(n2, m2).sum(qm[m2 + 1], qn[n2]); ++m2;
ret -= cache(n2, m2).sum(qn[n2 + 1], qm[m2]);
} else {
ret -= cache(n2, m2).sum(qn[n2 + 1], qn[n2]);
}
}
for (int i = 2; i <= wn; ++i) {
ret -= (i * k <= wN ? lN[i * k] : cache(n / i, m / i)).sum(i - 1, i);
}
return ret;
};
vector<i64> qN(vN + 2), qM(vM + 2); qM[0] = N;
for (int i = 1; i <= vN + 1; ++i) qN[i] = N / i;
for (int i = 1; i <= vM + 1; ++i) qM[i] = M / i;
for (int n = 1, m = M / N; n <= vN; ++n) {
if (qM[m + 1] >= qN[n + 1]) memoize(n, m, calc(n, m, wN + 1)), ++m;
memoize(n, m, calc(n, m, wN + 1));
}
for (int k = wN; k >= 1; --k) lN[k] = calc(N / k, M / k, k);
return lN[1];
}
struct Sum {
static constexpr u128 S1(u64 n) { return u128(n) * (n + 1) >> 1; }
static constexpr u128 S2(u64 n) { return u128(n) * (n + 1) * (2 * n + 1) / 6; }
Sum() : Sum(0, 0) {}
Sum(i64 N, i64 M)
: s00(u128(N) * M), s01(u128(N) * S1(M)), s10(S1(N) * M), s11(S1(N) * S1(M)) {}
Sum sum(i64 a, i64 b) const {
// (a, b]
auto ret = Sum(*this);
ret.s00 *= (b - a);
auto c1 = S1(b) - S1(a);
ret.s01 *= c1; ret.s10 *= c1;
ret.s11 *= S2(b) - S2(a);
return ret;
}
Sum& operator -= (const Sum& rhs) {
s00 -= rhs.s00; s01 -= rhs.s01; s10 -= rhs.s10; s11 -= rhs.s11;
return *this;
}
Sum operator - (const Sum& rhs) const { return Sum(*this) -= rhs; }
u128 s00, s01, s10, s11;
};
u128 naive(i64 N, i64 M) {
u128 ans = 0;
for (int dy = 1; dy < N; ++dy) {
for (int dx = 1; dx < M; ++dx) {
int g = __gcd(dx, dy) == 1;
ans += u128(M - dx) * (N - dy) * g;
}
}
ans *= 2;
ans += u128(N - 1) * M + u128(N) * (M - 1);
return ans;
}
u128 fast(i64 N, i64 M) {
auto ans = fast_sum<Sum>(N - 1, M - 1);
u128 ret = ans.s00 * N * M - ans.s01 * N - ans.s10 * M + ans.s11;
return ret * 2 + u128(N - 1) * M + u128(N) * (M - 1);
}
void solve() {
const int mod = 1e9 + 7;
int N, M;
while (~scanf("%d %d", &N, &M)) {
auto ans = fast(N, M);
printf("%llu\n", i64(ans % mod));
}
}
int main() {
clock_t beg = clock();
solve();
clock_t end = clock();
fprintf(stderr, "%.3f sec\n", double(end - beg) / CLOCKS_PER_SEC);
return 0;
}
Min_25