結果
問題 | No.1938 Lagrange Sum |
ユーザー | suisen |
提出日時 | 2022-05-14 00:10:16 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
CE
(最新)
AC
(最初)
|
実行時間 | - |
コード長 | 27,267 bytes |
コンパイル時間 | 3,550 ms |
コンパイル使用メモリ | 234,628 KB |
最終ジャッジ日時 | 2024-11-15 02:17:25 |
合計ジャッジ時間 | 4,421 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge5 |
(要ログイン)
コンパイルエラー時のメッセージ・ソースコードは、提出者また管理者しか表示できないようにしております。(リジャッジ後のコンパイルエラーは公開されます)
ただし、clay言語の場合は開発者のデバッグのため、公開されます。
ただし、clay言語の場合は開発者のデバッグのため、公開されます。
コンパイルメッセージ
main.cpp: In instantiation of 'void read(Args& ...) [with Args = {atcoder::static_modint<998244353, 0>}]': main.cpp:724:5: required from here main.cpp:201:26: error: no match for 'operator>>' (operand types are 'std::istream' {aka 'std::basic_istream<char>'} and 'atcoder::static_modint<998244353>') 201 | ( std::cin >> ... >> args ); | ~~~~~~~~~~~~~~~~~~~~~^~~~~~ In file included from /home/linuxbrew/.linuxbrew/Cellar/gcc@12/12.3.0/include/c++/12/sstream:38, from /home/linuxbrew/.linuxbrew/Cellar/gcc@12/12.3.0/include/c++/12/complex:45, from /home/linuxbrew/.linuxbrew/Cellar/gcc@12/12.3.0/include/c++/12/ccomplex:39, from /home/linuxbrew/.linuxbrew/Cellar/gcc@12/12.3.0/include/c++/12/x86_64-pc-linux-gnu/bits/stdc++.h:54, from main.cpp:5: /home/linuxbrew/.linuxbrew/Cellar/gcc@12/12.3.0/include/c++/12/istream:120:7: note: candidate: 'std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(__istream_type& (*)(__istream_type&)) [with _CharT = char; _Traits = std::char_traits<char>; __istream_type = std::basic_istream<char>]' 120 | operator>>(__istream_type& (*__pf)(__istream_type&)) | ^~~~~~~~ /home/linuxbrew/.linuxbrew/Cellar/gcc@12/12.3.0/include/c++/12/istream:120:36: note: no known conversion for argument 1 from 'atcoder::static_modint<998244353>' to 'std::basic_istream<char>::__istream_type& (*)(std::basic_istream<char>::__istream_type&)' {aka 'std::basic_istream<char>& (*)(std::basic_istream<char>&)'} 120 | operator>>(__istream_type& (*__pf)(__istream_type&)) | ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~ /home/linuxbrew/.linuxbrew/Cellar/gcc@12/12.3.0/include/c++/12/istream:124:7: note: candidate: 'std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(__ios_type& (*)(__ios_type&)) [with _CharT = char; _Traits = std::char_traits<char>; __istre
ソースコード
#pragma GCC target("avx2") #pragma GCC optimize("O3") #pragma GCC optimize("unroll-loops") #include <bits/stdc++.h> #include <limits> #include <type_traits> namespace suisen { // ! utility template <typename ...Types> using constraints_t = std::enable_if_t<std::conjunction_v<Types...>, std::nullptr_t>; template <bool cond_v, typename Then, typename OrElse> constexpr decltype(auto) constexpr_if(Then&& then, OrElse&& or_else) { if constexpr (cond_v) { return std::forward<Then>(then); } else { return std::forward<OrElse>(or_else); } } // ! function template <typename ReturnType, typename Callable, typename ...Args> using is_same_as_invoke_result = std::is_same<std::invoke_result_t<Callable, Args...>, ReturnType>; template <typename F, typename T> using is_uni_op = is_same_as_invoke_result<T, F, T>; template <typename F, typename T> using is_bin_op = is_same_as_invoke_result<T, F, T, T>; template <typename Comparator, typename T> using is_comparator = std::is_same<std::invoke_result_t<Comparator, T, T>, bool>; // ! integral template <typename T, typename = constraints_t<std::is_integral<T>>> constexpr int bit_num = std::numeric_limits<std::make_unsigned_t<T>>::digits; template <typename T, unsigned int n> struct is_nbit { static constexpr bool value = bit_num<T> == n; }; template <typename T, unsigned int n> static constexpr bool is_nbit_v = is_nbit<T, n>::value; // ? template <typename T> struct safely_multipliable {}; template <> struct safely_multipliable<int> { using type = long long; }; template <> struct safely_multipliable<long long> { using type = __int128_t; }; template <> struct safely_multipliable<unsigned int> { using type = unsigned long long; }; template <> struct safely_multipliable<unsigned long int> { using type = __uint128_t; }; template <> struct safely_multipliable<unsigned long long> { using type = __uint128_t; }; template <> struct safely_multipliable<float> { using type = float; }; template <> struct safely_multipliable<double> { using type = double; }; template <> struct safely_multipliable<long double> { using type = long double; }; template <typename T> using safely_multipliable_t = typename safely_multipliable<T>::type; } // namespace suisen // ! type aliases using i128 = __int128_t; using u128 = __uint128_t; template <typename T> using pq_greater = std::priority_queue<T, std::vector<T>, std::greater<T>>; template <typename T, typename U> using umap = std::unordered_map<T, U>; // ! macros (capital: internal macro) #define OVERLOAD2(_1,_2,name,...) name #define OVERLOAD3(_1,_2,_3,name,...) name #define OVERLOAD4(_1,_2,_3,_4,name,...) name #define REP4(i,l,r,s) for(std::remove_reference_t<std::remove_const_t<decltype(r)>>i=(l);i<(r);i+=(s)) #define REP3(i,l,r) REP4(i,l,r,1) #define REP2(i,n) REP3(i,0,n) #define REPINF3(i,l,s) for(std::remove_reference_t<std::remove_const_t<decltype(l)>>i=(l);;i+=(s)) #define REPINF2(i,l) REPINF3(i,l,1) #define REPINF1(i) REPINF2(i,0) #define RREP4(i,l,r,s) for(std::remove_reference_t<std::remove_const_t<decltype(r)>>i=(l)+fld((r)-(l)-1,s)*(s);i>=(l);i-=(s)) #define RREP3(i,l,r) RREP4(i,l,r,1) #define RREP2(i,n) RREP3(i,0,n) #define rep(...) OVERLOAD4(__VA_ARGS__, REP4 , REP3 , REP2 )(__VA_ARGS__) #define rrep(...) OVERLOAD4(__VA_ARGS__, RREP4 , RREP3 , RREP2 )(__VA_ARGS__) #define repinf(...) OVERLOAD3(__VA_ARGS__, REPINF3, REPINF2, REPINF1)(__VA_ARGS__) #define CAT_I(a, b) a##b #define CAT(a, b) CAT_I(a, b) #define UNIQVAR(tag) CAT(tag, __LINE__) #define loop(n) for (std::remove_reference_t<std::remove_const_t<decltype(n)>> UNIQVAR(loop_variable) = n; UNIQVAR(loop_variable) --> 0;) #define all(iterable) std::begin(iterable), std::end(iterable) #define input(type, ...) type __VA_ARGS__; read(__VA_ARGS__) #ifdef LOCAL # define debug(...) debug_internal(#__VA_ARGS__, __VA_ARGS__) template <class T, class... Args> void debug_internal(const char* s, T&& first, Args&&... args) { constexpr const char* prefix = "[\033[32mDEBUG\033[m] "; constexpr const char* open_brakets = sizeof...(args) == 0 ? "" : "("; constexpr const char* close_brakets = sizeof...(args) == 0 ? "" : ")"; std::cerr << prefix << open_brakets << s << close_brakets << ": " << open_brakets << std::forward<T>(first); ((std::cerr << ", " << std::forward<Args>(args)), ...); std::cerr << close_brakets << "\n"; } #else # define debug(...) void(0) #endif // ! I/O utilities // pair template <typename T, typename U> std::ostream& operator<<(std::ostream& out, const std::pair<T, U> &a) { return out << a.first << ' ' << a.second; } // tuple template <unsigned int N = 0, typename ...Args> std::ostream& operator<<(std::ostream& out, const std::tuple<Args...> &a) { if constexpr (N >= std::tuple_size_v<std::tuple<Args...>>) { return out; } else { out << std::get<N>(a); if constexpr (N + 1 < std::tuple_size_v<std::tuple<Args...>>) { out << ' '; } return operator<<<N + 1>(out, a); } } // vector template <typename T> std::ostream& operator<<(std::ostream& out, const std::vector<T> &a) { for (auto it = a.begin(); it != a.end();) { out << *it; if (++it != a.end()) out << ' '; } return out; } // array template <typename T, size_t N> std::ostream& operator<<(std::ostream& out, const std::array<T, N> &a) { for (auto it = a.begin(); it != a.end();) { out << *it; if (++it != a.end()) out << ' '; } return out; } inline void print() { std::cout << '\n'; } template <typename Head, typename... Tail> inline void print(const Head &head, const Tail &...tails) { std::cout << head; if (sizeof...(tails)) std::cout << ' '; print(tails...); } template <typename Iterable> auto print_all(const Iterable& v, std::string sep = " ", std::string end = "\n") -> decltype(std::cout << *v.begin(), void()) { for (auto it = v.begin(); it != v.end();) { std::cout << *it; if (++it != v.end()) std::cout << sep; } std::cout << end; } // pair template <typename T, typename U> std::istream& operator>>(std::istream& in, std::pair<T, U> &a) { return in >> a.first >> a.second; } // tuple template <unsigned int N = 0, typename ...Args> std::istream& operator>>(std::istream& in, std::tuple<Args...> &a) { if constexpr (N >= std::tuple_size_v<std::tuple<Args...>>) { return in; } else { return operator>><N + 1>(in >> std::get<N>(a), a); } } // vector template <typename T> std::istream& operator>>(std::istream& in, std::vector<T> &a) { for (auto it = a.begin(); it != a.end(); ++it) in >> *it; return in; } // array template <typename T, size_t N> std::istream& operator>>(std::istream& in, std::array<T, N> &a) { for (auto it = a.begin(); it != a.end(); ++it) in >> *it; return in; } template <typename ...Args> void read(Args &...args) { ( std::cin >> ... >> args ); } // ! integral utilities // Returns pow(-1, n) template <typename T> constexpr inline int pow_m1(T n) { return -(n & 1) | 1; } // Returns pow(-1, n) template <> constexpr inline int pow_m1<bool>(bool n) { return -int(n) | 1; } // Returns floor(x / y) template <typename T> constexpr inline T fld(const T x, const T y) { return (x ^ y) >= 0 ? x / y : (x - (y + pow_m1(y >= 0))) / y; } template <typename T> constexpr inline T cld(const T x, const T y) { return (x ^ y) <= 0 ? x / y : (x + (y + pow_m1(y >= 0))) / y; } template <typename T, suisen::constraints_t<suisen::is_nbit<T, 16>> = nullptr> constexpr inline int popcount(const T x) { return __builtin_popcount(x); } template <typename T, suisen::constraints_t<suisen::is_nbit<T, 32>> = nullptr> constexpr inline int popcount(const T x) { return __builtin_popcount(x); } template <typename T, suisen::constraints_t<suisen::is_nbit<T, 64>> = nullptr> constexpr inline int popcount(const T x) { return __builtin_popcountll(x); } template <typename T, suisen::constraints_t<suisen::is_nbit<T, 16>> = nullptr> constexpr inline int count_lz(const T x) { return x ? __builtin_clz(x) : suisen::bit_num<T>; } template <typename T, suisen::constraints_t<suisen::is_nbit<T, 32>> = nullptr> constexpr inline int count_lz(const T x) { return x ? __builtin_clz(x) : suisen::bit_num<T>; } template <typename T, suisen::constraints_t<suisen::is_nbit<T, 64>> = nullptr> constexpr inline int count_lz(const T x) { return x ? __builtin_clzll(x) : suisen::bit_num<T>; } template <typename T, suisen::constraints_t<suisen::is_nbit<T, 16>> = nullptr> constexpr inline int count_tz(const T x) { return x ? __builtin_ctz(x) : suisen::bit_num<T>; } template <typename T, suisen::constraints_t<suisen::is_nbit<T, 32>> = nullptr> constexpr inline int count_tz(const T x) { return x ? __builtin_ctz(x) : suisen::bit_num<T>; } template <typename T, suisen::constraints_t<suisen::is_nbit<T, 64>> = nullptr> constexpr inline int count_tz(const T x) { return x ? __builtin_ctzll(x) : suisen::bit_num<T>; } template <typename T> constexpr inline int floor_log2(const T x) { return suisen::bit_num<T> - 1 - count_lz(x); } template <typename T> constexpr inline int ceil_log2(const T x) { return floor_log2(x) + ((x & -x) != x); } template <typename T> constexpr inline int kth_bit(const T x, const unsigned int k) { return (x >> k) & 1; } template <typename T> constexpr inline int parity(const T x) { return popcount(x) & 1; } struct all_subset { struct all_subset_iter { const int s; int t; constexpr all_subset_iter(int s) : s(s), t(s + 1) {} constexpr auto operator*() const { return t; } constexpr auto operator++() {} constexpr auto operator!=(std::nullptr_t) { return t ? (--t &= s, true) : false; } }; int s; constexpr all_subset(int s) : s(s) {} constexpr auto begin() { return all_subset_iter(s); } constexpr auto end() { return nullptr; } }; // ! container template <typename T, typename Comparator, suisen::constraints_t<suisen::is_comparator<Comparator, T>> = nullptr> auto priqueue_comp(const Comparator comparator) { return std::priority_queue<T, std::vector<T>, Comparator>(comparator); } template <typename Iterable> auto isize(const Iterable &iterable) -> decltype(int(iterable.size())) { return iterable.size(); } template <typename T, typename Gen, suisen::constraints_t<suisen::is_same_as_invoke_result<T, Gen, int>> = nullptr> auto generate_vector(int n, Gen generator) { std::vector<T> v(n); for (int i = 0; i < n; ++i) v[i] = generator(i); return v; } template <typename T> auto generate_range_vector(T l, T r) { return generate_vector(r - l, [l](int i) { return l + i; }); } template <typename T> auto generate_range_vector(T n) { return generate_range_vector(0, n); } template <typename T> void sort_unique_erase(std::vector<T> &a) { std::sort(a.begin(), a.end()); a.erase(std::unique(a.begin(), a.end()), a.end()); } template <typename InputIterator, typename BiConsumer> auto foreach_adjacent_values(InputIterator first, InputIterator last, BiConsumer f) -> decltype(f(*first++, *last), void()) { if (first != last) for (auto itr = first, itl = itr++; itr != last; itl = itr++) f(*itl, *itr); } template <typename Container, typename BiConsumer> auto foreach_adjacent_values(Container c, BiConsumer f) -> decltype(c.begin(), c.end(), void()){ foreach_adjacent_values(c.begin(), c.end(), f); } // ! other utilities // x <- min(x, y). returns true iff `x` has chenged. template <typename T> inline bool chmin(T &x, const T &y) { if (y >= x) return false; x = y; return true; } // x <- max(x, y). returns true iff `x` has chenged. template <typename T> inline bool chmax(T &x, const T &y) { if (y <= x) return false; x = y; return true; } namespace suisen {} using namespace suisen; using namespace std; struct io_setup { io_setup(int precision = 20) { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); std::cout << std::fixed << std::setprecision(precision); } } io_setup_ {}; // ! code from here #include <atcoder/modint> #include <atcoder/convolution> using mint = atcoder::modint998244353; std::istream& operator>>(std::istream& in, mint &a) { long long e; in >> e; a = e; return in; } std::ostream& operator<<(std::ostream& out, const mint &a) { out << a.val(); return out; } #include <deque> #include <vector> #include <algorithm> #include <cassert> #include <iostream> namespace suisen { template <typename mint> class inv_mods { public: inv_mods() {} inv_mods(int n) { ensure(n); } const mint& operator[](int i) const { ensure(i); return invs[i]; } static void ensure(int n) { int sz = invs.size(); if (sz < 2) invs = {0, 1}, sz = 2; if (sz < n + 1) { invs.resize(n + 1); for (int i = sz; i <= n; ++i) invs[i] = mint(mod - mod / i) * invs[mod % i]; } } private: static std::vector<mint> invs; static constexpr int mod = mint::mod(); }; template <typename mint> std::vector<mint> inv_mods<mint>::invs{}; } namespace suisen { template <typename mint> using convolution_t = std::vector<mint> (*)(const std::vector<mint> &, const std::vector<mint> &); template <typename mint> class FPS : public std::vector<mint> { public: using std::vector<mint>::vector; FPS(const std::initializer_list<mint> l) : std::vector<mint>::vector(l) {} FPS(const std::vector<mint> &v) : std::vector<mint>::vector(v) {} FPS(std::vector<mint> &&v) : std::vector<mint>::vector(std::move(v)) {} static void set_multiplication(convolution_t<mint> multiplication) { FPS<mint>::mult = multiplication; } inline const mint operator[](int n) const noexcept { return n <= deg() ? unsafe_get(n) : 0; } inline mint& operator[](int n) noexcept { ensure_deg(n); return unsafe_get(n); } inline int size() const noexcept { return std::vector<mint>::size(); } inline int deg() const noexcept { return size() - 1; } inline int normalize() { while (this->size() and this->back() == 0) this->pop_back(); return deg(); } inline FPS& pre_inplace(int max_deg) noexcept { if (deg() > max_deg) this->resize(std::max(0, max_deg + 1)); return *this; } inline FPS pre(int max_deg) const noexcept { return FPS(*this).pre_inplace(max_deg); } inline FPS operator+() const { return FPS(*this); } FPS operator-() const { FPS f(*this); for (auto &e : f) e = mint::mod() - e; return f; } inline FPS& operator++() { ++(*this)[0]; return *this; } inline FPS& operator--() { --(*this)[0]; return *this; } inline FPS& operator+=(const mint x) { (*this)[0] += x; return *this; } inline FPS& operator-=(const mint x) { (*this)[0] -= x; return *this; } FPS& operator+=(const FPS &g) { ensure_deg(g.deg()); for (int i = 0; i <= g.deg(); ++i) unsafe_get(i) += g.unsafe_get(i); return *this; } FPS& operator-=(const FPS &g) { ensure_deg(g.deg()); for (int i = 0; i <= g.deg(); ++i) unsafe_get(i) -= g.unsafe_get(i); return *this; } inline FPS& operator*=(const FPS &g) { return *this = FPS<mint>::mult(*this, g); } inline FPS& operator*=( FPS &&g) { return *this = FPS<mint>::mult(*this, g); } inline FPS& operator*=(const mint x) { for (auto &e : *this) e *= x; return *this; } FPS& operator/=(FPS &&g) { const int fd = normalize(), gd = g.normalize(); assert(gd >= 0); if (fd < gd) { this->clear(); return *this; } if (gd == 0) return *this *= g.unsafe_get(0).inv(); static constexpr int THRESHOLD_NAIVE_POLY_QUOTIENT = 256; if (gd <= THRESHOLD_NAIVE_POLY_QUOTIENT) { *this = std::move(naive_div_inplace(std::move(g), gd).first); return *this; } std::reverse(this->begin(), this->end()), std::reverse(g.begin(), g.end()); const int k = fd - gd; *this *= g.inv_inplace(k), this->resize(k + 1); std::reverse(this->begin(), this->end()); return *this; } FPS& operator%=(FPS &&g) { int fd = normalize(), gd = g.normalize(); assert(gd >= 0); if (fd < gd) return *this; if (gd == 0) { this->clear(); return *this; } static constexpr int THRESHOLD_NAIVE_REMAINDER = 256; if (gd <= THRESHOLD_NAIVE_REMAINDER) return naive_div_inplace(std::move(g), gd).second; *this -= g * (*this / g); return pre_inplace(gd - 1); } inline FPS& operator/=(const FPS &g) { return *this /= FPS(g); } inline FPS& operator%=(const FPS &g) { return *this %= FPS(g); } FPS& operator<<=(const int shamt) { this->insert(this->begin(), shamt, 0); return *this; } FPS& operator>>=(const int shamt) { if (shamt > size()) this->clear(); else this->erase(this->begin(), this->begin() + shamt); return *this; } inline FPS operator+(FPS &&g) const { return FPS(*this) += std::move(g); } inline FPS operator-(FPS &&g) const { return FPS(*this) -= std::move(g); } inline FPS operator*(FPS &&g) const { return FPS(*this) *= std::move(g); } inline FPS operator/(FPS &&g) const { return FPS(*this) /= std::move(g); } inline FPS operator%(FPS &&g) const { return FPS(*this) %= std::move(g); } inline FPS operator+(const FPS &g) const { return FPS(*this) += g; } inline FPS operator+(const mint x) const { return FPS(*this) += x; } inline FPS operator-(const FPS &g) const { return FPS(*this) -= g; } inline FPS operator-(const mint x) const { return FPS(*this) -= x; } inline FPS operator*(const FPS &g) const { return FPS(*this) *= g; } inline FPS operator*(const mint x) const { return FPS(*this) *= x; } inline FPS operator/(const FPS &g) const { return FPS(*this) /= g; } inline FPS operator%(const FPS &g) const { return FPS(*this) %= g; } inline friend FPS operator*(const mint x, const FPS &f) { return f * x; } inline friend FPS operator*(const mint x, FPS &&f) { return f *= x; } inline FPS operator<<(const int shamt) { return FPS(*this) <<= shamt; } inline FPS operator>>(const int shamt) { return FPS(*this) >>= shamt; } friend bool operator==(const FPS &f, const FPS &g) { int n = f.size(), m = g.size(); if (n < m) return g == f; for (int i = 0; i < m; ++i) if (f.unsafe_get(i) != g.unsafe_get(i)) return false; for (int i = m; i < n; ++i) if (f.unsafe_get(i) != 0) return false; return true; } FPS& diff_inplace() { if (this->size() == 0) return *this; for (int i = 1; i <= deg(); ++i) unsafe_get(i - 1) = unsafe_get(i) * i; this->pop_back(); return *this; } FPS& intg_inplace() { int d = deg(); ensure_deg(d + 1); for (int i = d; i >= 0; --i) unsafe_get(i + 1) = unsafe_get(i) * invs[i + 1]; unsafe_get(0) = 0; return *this; } FPS& inv_inplace(const int max_deg) { FPS res { unsafe_get(0).inv() }; for (int k = 1; k <= max_deg; k *= 2) { FPS tmp(this->pre(k * 2) * (res * res)); res *= 2, res -= tmp.pre_inplace(2 * k); } return *this = std::move(res), pre_inplace(max_deg); } FPS& log_inplace(const int max_deg) { FPS f_inv = inv(max_deg); diff_inplace(), *this *= f_inv, pre_inplace(max_deg - 1), intg_inplace(); return *this; } FPS& exp_inplace(const int max_deg) { FPS res {1}; for (int k = 1; k <= max_deg; k *= 2) res *= ++(pre(k * 2) - res.log(k * 2)), res.pre_inplace(k * 2); return *this = std::move(res), pre_inplace(max_deg); } FPS& pow_inplace(const long long k, const int max_deg) { int tlz = 0; while (tlz <= deg() and unsafe_get(tlz) == 0) ++tlz; if (tlz * k > max_deg) { this->clear(); return *this; } *this >>= tlz; mint base = (*this)[0]; *this *= base.inv(), log_inplace(max_deg), *this *= k, exp_inplace(max_deg), *this *= base.pow(k); return *this <<= tlz * k, pre_inplace(max_deg); } inline FPS diff() const { return FPS(*this).diff_inplace(); } inline FPS intg() const { return FPS(*this).intg_inplace(); } inline FPS inv(const int max_deg) const { return FPS(*this).inv_inplace(max_deg); } inline FPS log(const int max_deg) const { return FPS(*this).log_inplace(max_deg); } inline FPS exp(const int max_deg) const { return FPS(*this).exp_inplace(max_deg); } inline FPS pow(const long long k, const int max_deg) const { return FPS(*this).pow_inplace(k, max_deg); } private: static inline inv_mods<mint> invs; static convolution_t<mint> mult; inline void ensure_deg(int d) { if (deg() < d) this->resize(d + 1, 0); } inline const mint& unsafe_get(int i) const { return std::vector<mint>::operator[](i); } inline mint& unsafe_get(int i) { return std::vector<mint>::operator[](i); } std::pair<FPS, FPS&> naive_div_inplace(FPS &&g, const int gd) { const int k = deg() - gd; mint head_inv = g.unsafe_get(gd).inv(); FPS q(k + 1); for (int i = k; i >= 0; --i) { mint div = this->unsafe_get(i + gd) * head_inv; q.unsafe_get(i) = div; for (int j = 0; j <= gd; ++j) this->unsafe_get(i + j) -= div * g.unsafe_get(j); } return {q, pre_inplace(gd - 1)}; } }; template <typename mint> convolution_t<mint> FPS<mint>::mult = [](const auto &, const auto &) { std::cerr << "convolution function is not available." << std::endl; assert(false); return std::vector<mint>{}; }; } // namespace suisen template <typename mint> auto sqrt(suisen::FPS<mint> a) -> decltype(mint::mod(), suisen::FPS<mint>{}) { assert(false); } template <typename mint> auto log(suisen::FPS<mint> a) -> decltype(mint::mod(), suisen::FPS<mint>{}) { return a.log(a.deg()); } template <typename mint> auto exp(suisen::FPS<mint> a) -> decltype(mint::mod(), mint()) { return a.exp(a.deg()); } template <typename mint, typename T> auto pow(suisen::FPS<mint> a, T b) -> decltype(mint::mod(), mint()) { return a.pow(b, a.deg()); } template <typename mint> auto inv(suisen::FPS<mint> a) -> decltype(mint::mod(), suisen::FPS<mint>{}) { return a.inv(a.deg()); } namespace suisen { template <typename mint> std::vector<mint> multi_point_eval(const FPS<mint> &f, const std::vector<mint> &xs) { int m = xs.size(); int k = 1; while (k < m) k <<= 1; std::vector<FPS<mint>> seg(2 * k); for (int i = 0; i < m; ++i) seg[k + i] = FPS<mint> {-xs[i], 1}; for (int i = m; i < k; ++i) seg[k + i] = FPS<mint> {1}; for (int i = k - 1; i> 0; --i) seg[i] = seg[i * 2] * seg[i * 2 + 1]; seg[1] = f % seg[1]; for (int i = 2; i < k + m; ++i) seg[i] = seg[i / 2] % seg[i]; std::vector<mint> ys(m); for (int i = 0; i < m; ++i) ys[i] = seg[k + i][0]; return ys; } } // namespace suisen namespace suisen { // O(N(logN)^2) // return the vector p of length xs.size() s.t. p[i]=Π[j!=i](x[i]-x[j]) template <typename T> std::vector<T> product_of_differences(const std::vector<T> &xs) { // f(x):=Π_i(x-x[i]) // => f'(x)=Σ_i Π[j!=i](x-x[j]) // => f'(x[i])=Π[j!=i](x[i]-x[j]) const int n = xs.size(); std::deque<FPS<T>> dq; for (int i = 0; i < n; ++i) dq.push_back(FPS<T>{ -xs[i], T{1} }); while (dq.size() >= 2) { auto f = std::move(dq.front()); dq.pop_front(); auto g = std::move(dq.front()); dq.pop_front(); dq.push_back(f * g); } auto f = std::move(dq.front()); f.diff_inplace(); return multi_point_eval(f, xs); } // O(N(logN)^2+NlogP) template <typename T> T lagrange_interpolation(const std::vector<T> &xs, const std::vector<T> &ys, const T t) { const int n = xs.size(); assert(int(ys.size()) == n); T p{1}; for (int i = 0; i < n; ++i) p *= t - xs[i]; std::vector<T> w = product_of_differences(xs); T res{0}; for (int i = 0; i < n; ++i) { res += t == xs[i] ? ys[i] : ys[i] * p / (w[i] * (t - xs[i])); } return res; } template <typename T> T lagrange_interpolation(const std::vector<T> &ys, const T t) { const int n = ys.size(); T fac = 1; for (int i = 1; i < n; ++i) fac *= i; std::vector<T> fci(n), suf(n); fci[n - 1] = T(1) / fac; suf[n - 1] = 1; for (int i = n - 1; i > 0; --i) { fci[i - 1] = fci[i] * i; suf[i - 1] = suf[i] * (t - i); } T prf = 1, res = 0; for (int i = 0; i < n; ++i) { T val = ys[i] * prf * suf[i] * fci[i] * fci[n - i - 1]; if ((n - 1 - i) & 1) { res -= val; } else { res += val; } prf *= t - i; } return res; } template <typename mint> FPS<mint> polynomial_interpolation(const std::vector<mint> &xs, const std::vector<mint> &ys) { assert(xs.size() == ys.size()); int n = xs.size(); int k = 1; while (k < n) k <<= 1; std::vector<FPS<mint>> seg(k << 1), g(k << 1); for (int i = 0; i < n; ++i) seg[k + i] = FPS<mint> {-xs[i], 1}; for (int i = n; i < k; ++i) seg[k + i] = FPS<mint> {1}; for (int i = k - 1; i > 0; --i) { seg[i] = seg[i * 2] * seg[i * 2 + 1]; } g[1] = std::move(seg[1].diff_inplace()); for (int i = 1; i < k; ++i) { int l = 2 * i, r = l + 1; g[l] = g[i] % seg[l], g[r] = g[i] % seg[r]; } for (int i = 0; i < n; ++i) g[k + i] = FPS<mint> {ys[i] / g[k + i][0]}; for (int i = n; i < k; ++i) g[k + i] = FPS<mint> {0}; for (int i = k - 1; i > 0; --i) { int l = 2 * i, r = l + 1; g[i] = g[l] * seg[r] + g[r] * seg[l]; } return g[1]; } } // namespace suisen int main() { suisen::FPS<mint>::set_multiplication([](const auto &a, const auto &b) { return atcoder::convolution(a, b); }); input(int, n); input(mint, x); vector<mint> xs(n), ys(n); rep(i, n) read(xs[i], ys[i]); vector<mint> p = product_of_differences(xs); mint s = 0; rep(i, n) s += ys[i] / p[i]; mint prd = 1; rep(i, n) prd *= x - xs[i]; mint ans = 0; rep(i, n) { mint num = x == xs[i] ? p[i] : prd / (x - xs[i]); ans += (n * ys[i] / p[i] - s) * num; } print(ans); return 0; }