結果
問題 | No.1750 ラムドスウイルスの感染拡大-hard |
ユーザー |
|
提出日時 | 2021-11-19 21:58:06 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 355 ms / 2,000 ms |
コード長 | 22,572 bytes |
コンパイル時間 | 2,119 ms |
コンパイル使用メモリ | 206,020 KB |
最終ジャッジ日時 | 2025-01-25 20:20:19 |
ジャッジサーバーID (参考情報) |
judge4 / judge1 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 4 |
other | AC * 30 |
ソースコード
/*** author: Sooh* created: 19.11.2021 21:18:29**/#include<bits/stdc++.h>using namespace std;#if __has_include(<atcoder/all>)#include <utility>namespace atcoder {namespace internal {constexpr long long safe_mod(long long x, long long m) {x %= m;if (x < 0) x += m;return x;}struct barrett {unsigned int _m;unsigned long long im;barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}unsigned int umod() const { return _m; }unsigned int mul(unsigned int a, unsigned int b) const {unsigned long long z = a;z *= b;#ifdef _MSC_VERunsigned long long x;_umul128(z, im, &x);#elseunsigned long long x =(unsigned long long)(((unsigned __int128)(z)*im) >> 64);#endifunsigned int v = (unsigned int)(z - x * _m);if (_m <= v) v += _m;return v;}};constexpr long long pow_mod_constexpr(long long x, long long n, int m) {if (m == 1) return 0;unsigned int _m = (unsigned int)(m);unsigned long long r = 1;unsigned long long y = safe_mod(x, m);while (n) {if (n & 1) r = (r * y) % _m;y = (y * y) % _m;n >>= 1;}return r;}constexpr bool is_prime_constexpr(int n) {if (n <= 1) return false;if (n == 2 || n == 7 || n == 61) return true;if (n % 2 == 0) return false;long long d = n - 1;while (d % 2 == 0) d /= 2;for (long long a : {2, 7, 61}) {long long t = d;long long y = pow_mod_constexpr(a, t, n);while (t != n - 1 && y != 1 && y != n - 1) {y = y * y % n;t <<= 1;}if (y != n - 1 && t % 2 == 0) {return false;}}return true;}template <int n> constexpr bool is_prime = is_prime_constexpr(n);constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {a = safe_mod(a, b);if (a == 0) return {b, 0};long long s = b, t = a;long long m0 = 0, m1 = 1;while (t) {long long u = s / t;s -= t * u;m0 -= m1 * u; // |m1 * u| <= |m1| * s <= bauto tmp = s;s = t;t = tmp;tmp = m0;m0 = m1;m1 = tmp;}if (m0 < 0) m0 += b / s;return {s, m0};}constexpr int primitive_root_constexpr(int m) {if (m == 2) return 1;if (m == 167772161) return 3;if (m == 469762049) return 3;if (m == 754974721) return 11;if (m == 998244353) return 3;int divs[20] = {};divs[0] = 2;int cnt = 1;int x = (m - 1) / 2;while (x % 2 == 0) x /= 2;for (int i = 3; (long long)(i)*i <= x; i += 2) {if (x % i == 0) {divs[cnt++] = i;while (x % i == 0) {x /= i;}}}if (x > 1) {divs[cnt++] = x;}for (int g = 2;; g++) {bool ok = true;for (int i = 0; i < cnt; i++) {if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {ok = false;break;}}if (ok) return g;}}template <int m> constexpr int primitive_root = primitive_root_constexpr(m);} // namespace internal} // namespace atcoder#include <cassert>#include <numeric>#include <type_traits>namespace atcoder {namespace internal {#ifndef _MSC_VERtemplate <class T>using is_signed_int128 =typename std::conditional<std::is_same<T, __int128_t>::value ||std::is_same<T, __int128>::value,std::true_type,std::false_type>::type;template <class T>using is_unsigned_int128 =typename std::conditional<std::is_same<T, __uint128_t>::value ||std::is_same<T, unsigned __int128>::value,std::true_type,std::false_type>::type;template <class T>using make_unsigned_int128 =typename std::conditional<std::is_same<T, __int128_t>::value,__uint128_t,unsigned __int128>;template <class T>using is_integral = typename std::conditional<std::is_integral<T>::value ||is_signed_int128<T>::value ||is_unsigned_int128<T>::value,std::true_type,std::false_type>::type;template <class T>using is_signed_int = typename std::conditional<(is_integral<T>::value &&std::is_signed<T>::value) ||is_signed_int128<T>::value,std::true_type,std::false_type>::type;template <class T>using is_unsigned_int =typename std::conditional<(is_integral<T>::value &&std::is_unsigned<T>::value) ||is_unsigned_int128<T>::value,std::true_type,std::false_type>::type;template <class T>using to_unsigned = typename std::conditional<is_signed_int128<T>::value,make_unsigned_int128<T>,typename std::conditional<std::is_signed<T>::value,std::make_unsigned<T>,std::common_type<T>>::type>::type;#elsetemplate <class T> using is_integral = typename std::is_integral<T>;template <class T>using is_signed_int =typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,std::true_type,std::false_type>::type;template <class T>using is_unsigned_int =typename std::conditional<is_integral<T>::value &&std::is_unsigned<T>::value,std::true_type,std::false_type>::type;template <class T>using to_unsigned = typename std::conditional<is_signed_int<T>::value,std::make_unsigned<T>,std::common_type<T>>::type;#endiftemplate <class T>using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;template <class T>using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;template <class T> using to_unsigned_t = typename to_unsigned<T>::type;} // namespace internal} // namespace atcoder#include <cassert>#include <numeric>#include <type_traits>#ifdef _MSC_VER#include <intrin.h>#endifnamespace atcoder {namespace internal {struct modint_base {};struct static_modint_base : modint_base {};template <class T> using is_modint = std::is_base_of<modint_base, T>;template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;} // namespace internaltemplate <int m, std::enable_if_t<(1 <= m)>* = nullptr>struct static_modint : internal::static_modint_base {using mint = static_modint;public:static constexpr int mod() { return m; }static mint raw(int v) {mint x;x._v = v;return x;}static_modint() : _v(0) {}template <class T, internal::is_signed_int_t<T>* = nullptr>static_modint(T v) {long long x = (long long)(v % (long long)(umod()));if (x < 0) x += umod();_v = (unsigned int)(x);}template <class T, internal::is_unsigned_int_t<T>* = nullptr>static_modint(T v) {_v = (unsigned int)(v % umod());}static_modint(bool v) { _v = ((unsigned int)(v) % umod()); }unsigned int val() const { return _v; }mint& operator++() {_v++;if (_v == umod()) _v = 0;return *this;}mint& operator--() {if (_v == 0) _v = umod();_v--;return *this;}mint operator++(int) {mint result = *this;++*this;return result;}mint operator--(int) {mint result = *this;--*this;return result;}mint& operator+=(const mint& rhs) {_v += rhs._v;if (_v >= umod()) _v -= umod();return *this;}mint& operator-=(const mint& rhs) {_v -= rhs._v;if (_v >= umod()) _v += umod();return *this;}mint& operator*=(const mint& rhs) {unsigned long long z = _v;z *= rhs._v;_v = (unsigned int)(z % umod());return *this;}mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }mint operator+() const { return *this; }mint operator-() const { return mint() - *this; }mint pow(long long n) const {assert(0 <= n);mint x = *this, r = 1;while (n) {if (n & 1) r *= x;x *= x;n >>= 1;}return r;}mint inv() const {if (prime) {assert(_v);return pow(umod() - 2);} else {auto eg = internal::inv_gcd(_v, m);assert(eg.first == 1);return eg.second;}}friend mint operator+(const mint& lhs, const mint& rhs) {return mint(lhs) += rhs;}friend mint operator-(const mint& lhs, const mint& rhs) {return mint(lhs) -= rhs;}friend mint operator*(const mint& lhs, const mint& rhs) {return mint(lhs) *= rhs;}friend mint operator/(const mint& lhs, const mint& rhs) {return mint(lhs) /= rhs;}friend bool operator==(const mint& lhs, const mint& rhs) {return lhs._v == rhs._v;}friend bool operator!=(const mint& lhs, const mint& rhs) {return lhs._v != rhs._v;}private:unsigned int _v;static constexpr unsigned int umod() { return m; }static constexpr bool prime = internal::is_prime<m>;};template <int id> struct dynamic_modint : internal::modint_base {using mint = dynamic_modint;public:static int mod() { return (int)(bt.umod()); }static void set_mod(int m) {assert(1 <= m);bt = internal::barrett(m);}static mint raw(int v) {mint x;x._v = v;return x;}dynamic_modint() : _v(0) {}template <class T, internal::is_signed_int_t<T>* = nullptr>dynamic_modint(T v) {long long x = (long long)(v % (long long)(mod()));if (x < 0) x += mod();_v = (unsigned int)(x);}template <class T, internal::is_unsigned_int_t<T>* = nullptr>dynamic_modint(T v) {_v = (unsigned int)(v % mod());}dynamic_modint(bool v) { _v = ((unsigned int)(v) % mod()); }unsigned int val() const { return _v; }mint& operator++() {_v++;if (_v == umod()) _v = 0;return *this;}mint& operator--() {if (_v == 0) _v = umod();_v--;return *this;}mint operator++(int) {mint result = *this;++*this;return result;}mint operator--(int) {mint result = *this;--*this;return result;}mint& operator+=(const mint& rhs) {_v += rhs._v;if (_v >= umod()) _v -= umod();return *this;}mint& operator-=(const mint& rhs) {_v += mod() - rhs._v;if (_v >= umod()) _v -= umod();return *this;}mint& operator*=(const mint& rhs) {_v = bt.mul(_v, rhs._v);return *this;}mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }mint operator+() const { return *this; }mint operator-() const { return mint() - *this; }mint pow(long long n) const {assert(0 <= n);mint x = *this, r = 1;while (n) {if (n & 1) r *= x;x *= x;n >>= 1;}return r;}mint inv() const {auto eg = internal::inv_gcd(_v, mod());assert(eg.first == 1);return eg.second;}friend mint operator+(const mint& lhs, const mint& rhs) {return mint(lhs) += rhs;}friend mint operator-(const mint& lhs, const mint& rhs) {return mint(lhs) -= rhs;}friend mint operator*(const mint& lhs, const mint& rhs) {return mint(lhs) *= rhs;}friend mint operator/(const mint& lhs, const mint& rhs) {return mint(lhs) /= rhs;}friend bool operator==(const mint& lhs, const mint& rhs) {return lhs._v == rhs._v;}friend bool operator!=(const mint& lhs, const mint& rhs) {return lhs._v != rhs._v;}private:unsigned int _v;static internal::barrett bt;static unsigned int umod() { return bt.umod(); }};template <int id> internal::barrett dynamic_modint<id>::bt = 998244353;using modint998244353 = static_modint<998244353>;using modint1000000007 = static_modint<1000000007>;using modint = dynamic_modint<-1>;namespace internal {template <class T>using is_static_modint = std::is_base_of<internal::static_modint_base, T>;template <class T>using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;template <class> struct is_dynamic_modint : public std::false_type {};template <int id>struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};template <class T>using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;} // namespace internal} // namespace atcoderusing namespace atcoder;using mint = modint998244353;//using mint = modint1000000007;#endif#pragma region templateusing ll = long long;template <class T> using V = vector<T>;#define rep(i,n) for(int i=0;i<n;++i)#define all(x) (x).begin(), (x).end()#define rall(x) (x).rbegin(), (x).rend()#define sz(x) ((int)(x).size())#define pb push_back#define eb emplace_back#define fi first#define se second#ifdef LOCAL#define debug(var) do{std::cerr << "\033[1;36m" << #var << ": \033[0m";view(var);std::cerr << std::endl;}while(0)template<typename T> void view(T e){std::cerr << e;}template<typename T, typename K> void view(pair<T, K> e){std::cerr << "("; view(e.fi); std::cerr << ", "; view(e.se); std::cerr << ")";}template<typename T> void view(const set<T> &st){ std::cerr << "\n";for(const auto& e : st){view(e); std::cerr << " ";}}template<typename T, typename K> void view(const map<T, K> &mp){ std::cerr << "\n";for(const auto& [k, v]: mp){std::cerr << "("; view(k); std::cerr<< ", "; view(v); std::cerr << ") ";}}template<typename T> void view(const unordered_map<int, T> &mp){ std::cerr << "\n";for(const auto& [k, v]: mp){std::cerr << "("; view(k); std::cerr<< ", "; view(v); std::cerr << ") ";}}template<typename T> void view(const std::vector<T>& v){std::cerr << "\n";for(const auto& e : v){ view(e); std::cerr << " "; }}template<typename T> void view(const std::vector<std::vector<T> >& vv){std::cerr << "\n";int cnt = 0;for(const auto& v : vv){cerr << cnt << "th : ";view(v); cnt++; std::cerr << std::endl;}}#else#define debug(var) 0#endifll power(ll a, ll p){ll ret = 1; while(p){if(p & 1){ret = ret * a;} a = a * a; p >>= 1;} return ret;}ll modpow(ll a, ll p, ll mod){ll ret = 1; while(p){if(p & 1){ret = ret * a % mod;} a = a * a % mod; p >>= 1;} return ret;}ll modinv(ll a, ll m) {ll b = m, u = 1, v = 0; while (b) {ll t = a / b ;a -= t * b; swap(a, b);u -= t * v; swap(u, v);}u %= m;if (u < 0) u += m;return u;}template<class T, class K>bool chmax(T &a, const K b) { if (a<b) { a=b; return 1; } return 0; }template<class T, class K>bool chmin(T &a, const K b) { if (b<a) { a=b; return 1; } return 0; }#pragma endregionint dx[]={1,0,-1,0};int dy[]={0,1,0,-1};const int inf = 1001001001;const ll INF = 1001001001001001001ll;//const double pi = acos(-1);//const ll mod = 998244353;const ll mod = 1000000007;// reference : https://ei1333.github.io/luzhiled/snippets/math/matrix.html// gauss_jordan_F2 : https://atcoder.jp/contests/typical90/submissions/25903321// gauss_jordan : unverified// matrix exponentiation : verified in https://atcoder.jp/contests/abc129/tasks/abc129_f// matrix exponentiation (mod) : verified in https://atcoder.jp/contests/arc020/submissions/27320350template<class T>struct Matrix{std::vector<std::vector<T>> A;// ll modulo;Matrix(){}Matrix(int _n):A(_n, std::vector<T>(_n, 0)){}Matrix(int _n, int _m):A(_n, std::vector<T>(_m, 0)){}//Matrix(int _n, int _m, ll md):A(_n, std::vector<T>(_m, 0)){modulo = md;}Matrix(std::vector<std::vector<T>> &_A){ A = _A;}int height()const{return A.size();}int width()const{return A[0].size();}void multiply_vector(std::vector<T> &v){assert(width() == v.size());std::vector<T> res(height());for(int i = 0; i < height(); i++){for(int j = 0; j < width(); j++){res[i] += (A[i][j] * v[j]);//res[i] += (A[i][j] * v[j]) % modulo;//if(res[i] >= modulo) res[i] -= modulo;}}v.swap(res);return;}// the result will be in Bstd::pair<int, T> gauss_jordan(Matrix &B){int rank = 0;T ret = 1;B = Matrix(*this);int n = height(), m = width();for(int col = 0; col < m; col++){for(int i = rank; i < n; i++){if(B[i][col] != 0){if(i != rank) ret *= -1;swap(B[i], B[rank]);break;}}if(B[rank][col] == 0) continue;ret *= B[rank][col];for(int j = m - 1; j >= col; j--) B[rank][j] /= B[rank][col];for(int r = 0; r < n; r++){if(r == rank || B[r][col] == 0) continue;for(int c = m - 1; c > col; c--) B[r][c] -= B[r][col] * B[rank][c];B[r][col] = 0;}if(++rank == n) break;}return std::pair<int, T>(rank, ret);}Matrix inv(){ // 存在しないなら単位行列を返すint n = height(), m = width();assert(n = m);int rank = 0;Matrix B = Matrix(*this), C = identity(n);for(int col = 0; col < m; col++){for(int i = rank; i < n; i++){if(B[i][col] != 0){std::swap(B[i], B[rank]);std::swap(C[i], C[rank]);break;}}if(B[rank][col] == 0) return identity(n);for(int j = 0; j < m; j++) C[rank][j] /= B[rank][col];for(int j = m - 1; j >= col; j--) B[rank][j] /= B[rank][col];for(int r = 0; r < n; r++){if(r == rank || B[r][col] == 0) continue;for(int c = 0; c < m; c++) C[r][c] -= B[r][col]*C[rank][c];for(int c = m - 1; c > col; c--) B[r][c] -= B[r][col]*B[rank][c];B[r][col] = 0;}if(++rank == n) break;}return C;}Matrix LU_decomposition(){ // Lの対角部が1、LUの狭義下三角がLassert(height() == width());Matrix LU = Matrix(*this);int n = height();for(int k = 0; k < n; k++){for(int i = k + 1; i < n; i++){LU[i][k] /= LU[k][k];}for(int i = k + 1; i < n; i++){for(int j = k + 1; j < n; j++){LU[i][j] -= LU[j][k] * LU[k][i];}}}return LU;}T det(){assert(height() == width());Matrix B;auto[rank, ret] = gauss_jordan(B);if(rank < height()) return T(0);return ret;}Matrix identity(int n){Matrix I(n);for(int i = 0; i < height(); i++) I[i][i] = 1;return I;}Matrix &operator+=(const Matrix &B){int n = height(), m = width();assert(n == B.height() && m == B.width());for(int i = 0; i < n; i++) for(int j = 0; j < m; j++) (*this)[i][j] += B[i][j];return (*this);}Matrix &operator-=(const Matrix &B){int n = height(), m = width();assert(n == B.height() && m == B.width());for(int i = 0; i < n; i++) for(int j = 0; j < m; j++) (*this)[i][j] -= B[i][j];return (*this);}Matrix &operator*=(const Matrix &B){int n = height(), m = width(), l = B.width();assert(m == B.height());std::vector<std::vector<T>> C(n, std::vector<T>(m, 0));for(int i = 0; i < n; i++) for(int j = 0; j < l; j++){for(int k = 0; k < m; k++){C[i][j] += ((*this)[i][k] * B[k][j]);//C[i][j] += ((*this)[i][k] * B[k][j]) % modulo;//if(C[i][j] >= modulo) C[i][j] -= modulo;}}A.swap(C);return (*this);}Matrix &operator^=(long long k){Matrix B = Matrix::identity(height());// B.modulo = this->modulo;while(k){if(k & 1) B *= *this;*this *= *this;k >>= 1;}A.swap(B.A);return (*this);}Matrix operator+(const Matrix &B)const{return (Matrix(*this) += B);}Matrix operator-(const Matrix &B)const{return (Matrix(*this) -= B);}Matrix operator*(const Matrix &B)const{return (Matrix(*this) *= B);}Matrix operator^(const long long k)const{return (Matrix(*this) ^= k);}inline std::vector<T> &operator[](int k){ return A.at(k);}inline const std::vector<T> &operator[](int k)const{ return A.at(k);}friend ostream &operator<<(ostream &os, Matrix &p){size_t n = p.height(), m = p.width();for(int i = 0; i < n; i++) {os << "[";for(int j = 0; j < m; j++) {os << p[i][j] << (j + 1 == m ? "]\n" : ",");}}return (os);}};int main(){cin.tie(nullptr);ios::sync_with_stdio(false);//cout << fixed << setprecision(20);ll n, m, t; cin >> n >> m >> t;V<V<int>> G(n);Matrix<mint> A(n, n);rep(i,m){int a, b; cin >> a >> b;A[a][b] = A[b][a] = 1;}A ^= t;V<mint> dp(n);dp[0] = 1;A.multiply_vector(dp);cout << dp[0].val() << endl;}