結果
問題 |
No.723 2つの数の和
|
ユーザー |
|
提出日時 | 2018-08-06 16:11:13 |
言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 73 ms / 2,000 ms |
コード長 | 3,358 bytes |
コンパイル時間 | 955 ms |
コンパイル使用メモリ | 90,532 KB |
実行使用メモリ | 12,392 KB |
最終ジャッジ日時 | 2024-09-19 18:13:01 |
合計ジャッジ時間 | 3,394 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge4 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 22 |
ソースコード
#include <cmath> #include <iostream> #include <tuple> #include <vector> using namespace std; using i64 = long long; // {{{ mod_mul, extgcd, mod_inv, mod_pow inline i64 mod_mul(const i64& x, const i64& y, const i64& m) { // yとmの最大ビット長はともに48ビット。 // http://codeforces.com/blog/entry/15884 // 12 < floor(63 - log2(MAX_VALUE)) = 15 // 0xfff = (1<<12) - 1 i64 b, res = y * (x & 0xfff); res += (b=(y<<12) % m) * ((x>>12) & 0xfff); res += (b=(b<<12) % m) * ((x>>24) & 0xfff); res += (b<<12) % m * ((x>>36) & 0xfff); res %= m; return res; } inline tuple<i64, i64, i64> extgcd(const i64& x, const i64& y) { if(y == 0) { return {1LL, 0LL, x}; } i64 a, b, d; tie(a, b, d) = extgcd(y, x%y); return {b, a-x/y*b, d}; } inline i64 mod_inv(const i64& a, const i64& m) { i64 x, _, d; tie(x, _, d) = extgcd(a, m); return (x % m + m) % m; } inline i64 mod_pow(const i64& a, const i64& r, const i64& n, const i64& m) { if(n == 0) { return r; } if(n & 1) { return mod_pow(a, mod_mul(a, r, m), n-1, m); } return mod_pow(mod_mul(a, a, m), r, n>>1, m); } inline i64 mod_pow(const i64 a, const i64 n, const i64 m) { return mod_pow(a, 1, n, m); } // }}} struct FMT { static vector<i64> convol (const vector<i64>& a, const vector<i64>& b); static void convol2(vector<i64>& a, vector<i64>& b); // a に答えが入る。メモリ節約が目的。fftmulで使用。 private: static constexpr i64 N = 5LL << 37; static constexpr i64 O = 2003LL; static constexpr i64 M = N * 211 + 1; static void fmt(vector<i64>&); static void ifmt(vector<i64>&); static void myfmt(vector<i64>&, const bool); }; // {{{ FMT 実装 void FMT::myfmt(vector<i64> &a, const bool inv) { const int n = int(a.size()); for(int H=1, W=n>>1; H<n; H<<=1, W>>=1) { vector<i64> y = a; i64 r = mod_pow(O, N/(H*2), M); if(inv) { r = mod_inv(r, M); } i64 w = 1; for(int k=0; k<H; ++k) { for(int j=0; j<W; ++j) { i64 y0 = y[2*W*k+j], y1 = mod_mul(y[2*W*k+j+W], w, M); a[W* k +j] = y0 + y1 < M ? y0 + y1 : y0 + y1 - M; a[W*(k+H)+j] = y0 < y1 ? y0 - y1 + M : y0 - y1; } w = mod_mul(w, r, M); } } } void FMT::fmt(vector<i64> &a) { myfmt(a, false); } void FMT::ifmt(vector<i64> &a) { myfmt(a, true); const int n = int(a.size()); i64 inv = mod_inv(n, M); for(int i=0; i<n; ++i) { a[i] = mod_mul(a[i], inv, M); } } vector<i64> FMT::convol(const vector<i64> &a, const vector<i64> &b) { int n = 1; while(n <= a.size() + b.size()) { n <<= 1; } vector<i64> ta = a, tb = b, c(n); ta.resize(n); tb.resize(n); fmt(ta); fmt(tb); for(int i=0; i<n; ++i) { c[i] = mod_mul(ta[i], tb[i], M); } ifmt(c); return c; } void FMT::convol2(vector<i64> &a, vector<i64> &b) { int n = 1; while(n <= a.size() + b.size()) { n <<= 1; } a.resize(n); b.resize(n); fmt(a); fmt(b); for(int i=0; i<n; ++i) { a[i] = mod_mul(a[i], b[i], M); } ifmt(a); } // }}} constexpr int N = int(powl(10, 5)) + 10; int main(void) { int n; i64 x; scanf("%d%lld", &n, &x); vector<i64> a(N); for(int i=0; i<n; ++i) { int v; scanf("%d", &v); ++a[v]; } vector<i64> c = FMT::convol(a, a); i64 res = 0; if(x < c.size()) { res = c[x]; } printf("%lld\n", res); return 0; }