結果
問題 | No.2979 直角三角形の個数 |
ユーザー |
![]() |
提出日時 | 2024-12-03 14:52:01 |
言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 2,945 ms / 4,000 ms |
コード長 | 4,411 bytes |
コンパイル時間 | 3,307 ms |
コンパイル使用メモリ | 278,256 KB |
実行使用メモリ | 37,888 KB |
最終ジャッジ日時 | 2024-12-03 14:52:15 |
合計ジャッジ時間 | 13,318 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge1 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 26 |
ソースコード
#include<bits/stdc++.h>namespace {#pragma GCC diagnostic ignored "-Wunused-function"#include<atcoder/all>#pragma GCC diagnostic warning "-Wunused-function"using namespace std;using namespace atcoder;#define rep(i,n) for(int i = 0; i < (int)(n); i++)#define rrep(i,n) for(int i = (int)(n) - 1; i >= 0; i--)#define all(x) begin(x), end(x)#define rall(x) rbegin(x), rend(x)template<class T> bool chmax(T& a, const T& b) { if (a < b) { a = b; return true; } else return false; }template<class T> bool chmin(T& a, const T& b) { if (b < a) { a = b; return true; } else return false; }using ll = long long;using P = pair<int,int>;using VI = vector<int>;using VVI = vector<VI>;using VL = vector<ll>;using VVL = vector<VL>;pair<vector<int>, vector<int>> primes_lpf(const int n) {vector<int> primes; primes.reserve(n / 10);vector<int> lpf(n + 1);for (int i = 2; i <= n; i += 2) lpf[i] = 2;for (int i = 3; i <= n; i += 6) lpf[i] = 3;if (2 <= n) primes.push_back(2);if (3 <= n) primes.push_back(3);// 5 * x <= n, x <= floor(n / 5)const int n5 = n / 5;int x = 5;char add_next = 2;for (; x <= n5; x += add_next, add_next ^= 0x2 ^ 4) {int px = lpf[x];if (px == 0) {lpf[x] = px = x;primes.push_back(x);}for (int i = 2;; ++i) {int q = primes[i];int y = q * x;if (y > n) break;lpf[y] = q;if (q == px) break;}}for (; x <= n; x += add_next, add_next ^= 0x2 ^ 4) {if (lpf[x] == 0) {lpf[x] = x;primes.push_back(x);}}return {move(primes), move(lpf)};}constexpr int PSIZE = 1010000;auto [primes, lpf] = primes_lpf(PSIZE);template <integral T>T isqrt(T x) {assert (x >= 0);if (x < 1 << 24) return sqrt((float)x);else if (x < 1LL << 52) return sqrt(x);else return sqrtl(x);}ll qcount(ll q) {// x<y<=min(2x-1, [q/x])// sum rhs - lhs over x<=2x-1, x<=[q/x] <=> 1<=x<=isqrt(q)// 2x-1<[q/x] <=> 2x<=[q/x] <=> 2x<=q/x <=> x<=isqrt(q/2)// (0, x1], (x1, x2]int x1 = isqrt(q / 2), x2 = isqrt(q);// sum rhs// 1+3+...+2x1-1 = x1^2ll res = (ll)x1 * x1;for (int i = x1 + 1; i <= x2; i++) res += q / i;// sum lhs// 1+2+...+x2res -= (ll)x2 * (x2 + 1) / 2;return res;}template <class T>vector<T> list_quotients(T n) {vector<T> q;int sq = isqrt(n);// floor(n/sq)==sq// iff floor((n-sq^2)/sq)==0// iff n-sq^2<sqbool dup = n < T(sq + 1) * sq;q.reserve(2 * sq - dup);for (int i = 1; i <= sq; i++) q.emplace_back(n / i);for (int i = sq - dup; i >= 1; i--) q.emplace_back(i);return q;}} int main() {ios::sync_with_stdio(false);cin.tie(0);ll N;cin >> N;N /= 2;auto qs = list_quotients(N);const int sq = isqrt(N), sz = qs.size();auto get_idx = [&](ll x) {int idx = x <= sq ? sz - (int)x : int(N / x) - 1;assert(0 <= idx && idx < sz);assert(qs[idx] == x);return idx;};VI coeff(sq + 1);coeff[1] = 1;for (int i = 2; i <= sq; i++) {int j = i / lpf[i];if (lpf[i] != lpf[j]) coeff[i] = -coeff[j];}// for (int e2 = 0; N >> e2; e2++) {// ll add = 0;// ll n = N >> e2;// for (int i = 1; (ll)i * i <= n; i++) add += coeff[i] * ans_memo[get_idx(n / ((ll)i * i))];// ans += e2 % 2 == 0 ? add : -add;// }VI mul(sz);for (int i = 1; (ll)i * i <= N; i += 2) {ll v = N / ((ll)i * i);mul[get_idx(v)] += coeff[i];// ans += coeff[i] * ans_memo[get_idx(v)];v /= 2;if (v) {// ans -= coeff[i] * ans_memo[get_idx(v)];mul[get_idx(v)] -= coeff[i];}}// int cnt = 0;// rep(i, sz) cnt += mul[i] != 0;// cout << cnt <<endl;// exit(0);// VL memo(sz);// rep(i, sz) memo[i] = qcount(qs[i]);// exit(0);// VL ans_memo(sz);VL mul2(sz);rep(i, sz) if (mul[i]) {ll N = qs[i];// ll ans = 0;for (ll q = 1, q_pre = 0;;) {ll ub = N / q;if (ub == 0) break;ll add = q - q_pre;// ans += add * memo[get_idx(ub)];mul2[get_idx(ub)] += add * mul[i];if (q == N) break;q_pre = q;q = N / (N / (q + 1));}// ans_memo[i] = ans;}// rep(i, sz) cout << qs[i] << ' ' << memo[i] << '\n';ll ans = 0;rep(i, sz) if (mul2[i]) ans += mul2[i] * qcount(qs[i]);cout << ans << '\n';// int cnt = 0;// rep(i, sz) cnt += mul2[i] != 0;// cout << cnt << endl;// cout << sz << endl;}