結果
問題 | No.2979 直角三角形の個数 |
ユーザー |
👑 |
提出日時 | 2024-12-04 04:29:36 |
言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 2,122 ms / 4,000 ms |
コード長 | 4,893 bytes |
コンパイル時間 | 1,738 ms |
コンパイル使用メモリ | 155,236 KB |
実行使用メモリ | 168,908 KB |
最終ジャッジ日時 | 2024-12-04 04:29:54 |
合計ジャッジ時間 | 12,722 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge4 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 26 |
ソースコード
#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 <limits>#include <map>#include <numeric>#include <queue>#include <random>#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; }#define COLOR(s) ("\x1b[" s "m")// cannot use count// no move constructor (==> use pointer for merge tech)// unordered_set by value: __gnu_pbds::null_type// no erase(iterator)#include <ext/pb_ds/assoc_container.hpp>using __gnu_pbds::gp_hash_table;// https://codeforces.com/blog/entry/62393#include <chrono>struct Hash {static uint64_t splitmix64(uint64_t x) {// http://xorshift.di.unimi.it/splitmix64.cx += 0x9e3779b97f4a7c15;x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;x = (x ^ (x >> 27)) * 0x94d049bb133111eb;return x ^ (x >> 31);}size_t operator()(uint64_t x) const {static const uint64_t FIXED_RANDOM = std::chrono::steady_clock::now().time_since_epoch().count();return splitmix64(x + FIXED_RANDOM);}size_t operator()(const pair<int, int> &a) const {return operator()((uint64_t)a.first << 32 | a.second);}};template <class K> using Set = gp_hash_table<K, __gnu_pbds::null_type, Hash>;template <class K, class V> using Map = gp_hash_table<K, V, Hash>;inline long long divide(long long a, int b) {return a / b;}inline long long divide(long long a, long long b) {return a / b;}// quo[i - 1] < x <= quo[i] <=> floor(N/x) = quo[len - i] (1 <= i <= len - 1)struct Quotients {long long N;int N2;int len;Quotients(long long N_ = 0) : N(N_) {N2 = sqrt(static_cast<long double>(N));len = 2 * N2 + ((static_cast<long long>(N2) * (N2 + 1) <= N) ? 1 : 0);}long long operator[](int i) const {return (i <= N2) ? i : divide(N, len - i);}int indexOf(long long x) const {return (x <= N2) ? x : (len - divide(N, x));}friend std::ostream &operator<<(std::ostream &os, const Quotients &quo) {os << "[";for (int i = 0; i < quo.len; ++i) {if (i > 0) os << ", ";os << quo[i];}os << "]";return os;}};/*k (m^2-n^2, 2mn, m^2+n^2)\sum[k,m,n] [gcd(m, n) = 1] [m != n (mod 2)] [1 <= n < m] [2km(m+n) <= N]= \sum[k,m,n] (\sum[d] [d | m] [d | n] \mu(d)) [m != n (mod 2)] [1 <= n < m] [km(m+n) <= N/2]= \sum[d] [2 !| d] \mu(d) \sum[k,m,n] [m != n (mod 2)] [1 <= n < m] [km(m+n) <= N/2/d^2]*/constexpr int K = 40'000'000;int small[K + 1];void init() {for (Int m = 1; m * (m + 1) <= K; ++m) {for (Int n = (m & 1) + 1; m * (m + n) <= K && n < m; n += 2) {++small[m * (m + n)];}}for (Int k = 1; k <= K; ++k) small[k] += small[k - 1];}Map<Int, Int> cache1;Int solve1(Int N) {if (N <= K) return small[N];auto it = cache1.find(N);if (it != cache1.end()) return it->second;const Quotients quo(N);Int ret = 0;for (Int m = 1; m * (m + 1) <= N; ++m) {ret += ((min(N / m, 2 * m - 1) + 1) / 2 - (m + 1) / 2);}return cache1[N] = ret;}Map<Int, Int> cache;Int solve(Int N) {auto it = cache.find(N);if (it != cache.end()) return it->second;const Quotients quo(N);Int ret = 0;for (int i = 1; i < quo.len; ++i) {ret += (quo[i] - quo[i - 1]) * solve1(quo[quo.len - i]);}return cache[N] = ret;}constexpr int LIM = 1'000'010;int lpf[LIM], moe[LIM];int main() {for (int p = 2; p < LIM; ++p) lpf[p] = p;for (int n = 1; n < LIM; ++n) moe[n] = 1;for (int p = 2; p < LIM; ++p) if (lpf[p] == p) {for (int n = p; n < LIM; n += p) {chmin(lpf[n], p);moe[n] = -moe[n];}}for (int d = 2; d*d < LIM; ++d) if (moe[d]) {for (int n = d*d; n < LIM; n += d*d) moe[n] = 0;}// pv(moe,moe+31);init();Int N;for (; ~scanf("%lld", &N); ) {N /= 2;Int ans = 0;for (Int d = 1; d*d <= N; d += 2) if (moe[d]) {ans += moe[d] * solve(N / (d*d));}printf("%lld\n", ans);}return 0;}