結果
問題 | No.1112 冥界の音楽 |
ユーザー | ysuzuki5321 |
提出日時 | 2023-10-25 05:46:53 |
言語 | C++14 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 52 ms / 2,000 ms |
コード長 | 52,351 bytes |
コンパイル時間 | 5,674 ms |
コンパイル使用メモリ | 250,076 KB |
実行使用メモリ | 6,944 KB |
最終ジャッジ日時 | 2024-09-25 01:11:05 |
合計ジャッジ時間 | 7,111 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge4 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
6,812 KB |
testcase_01 | AC | 2 ms
6,944 KB |
testcase_02 | AC | 2 ms
6,944 KB |
testcase_03 | AC | 2 ms
6,940 KB |
testcase_04 | AC | 2 ms
6,944 KB |
testcase_05 | AC | 2 ms
6,944 KB |
testcase_06 | AC | 4 ms
6,944 KB |
testcase_07 | AC | 2 ms
6,944 KB |
testcase_08 | AC | 2 ms
6,944 KB |
testcase_09 | AC | 3 ms
6,940 KB |
testcase_10 | AC | 2 ms
6,940 KB |
testcase_11 | AC | 2 ms
6,940 KB |
testcase_12 | AC | 2 ms
6,944 KB |
testcase_13 | AC | 2 ms
6,940 KB |
testcase_14 | AC | 14 ms
6,940 KB |
testcase_15 | AC | 5 ms
6,940 KB |
testcase_16 | AC | 1 ms
6,944 KB |
testcase_17 | AC | 6 ms
6,940 KB |
testcase_18 | AC | 6 ms
6,944 KB |
testcase_19 | AC | 2 ms
6,944 KB |
testcase_20 | AC | 3 ms
6,940 KB |
testcase_21 | AC | 14 ms
6,940 KB |
testcase_22 | AC | 14 ms
6,944 KB |
testcase_23 | AC | 5 ms
6,944 KB |
testcase_24 | AC | 2 ms
6,940 KB |
testcase_25 | AC | 2 ms
6,940 KB |
testcase_26 | AC | 2 ms
6,940 KB |
testcase_27 | AC | 2 ms
6,944 KB |
testcase_28 | AC | 3 ms
6,944 KB |
testcase_29 | AC | 2 ms
6,944 KB |
testcase_30 | AC | 16 ms
6,940 KB |
testcase_31 | AC | 2 ms
6,944 KB |
testcase_32 | AC | 17 ms
6,944 KB |
testcase_33 | AC | 2 ms
6,940 KB |
testcase_34 | AC | 2 ms
6,944 KB |
testcase_35 | AC | 2 ms
6,940 KB |
testcase_36 | AC | 52 ms
6,944 KB |
ソースコード
#include <stdio.h>#include <sstream>#include <string.h>#include <vector>#include <map>#include <algorithm>#include <utility>#include <set>#include <cctype>#include <queue>#include <stack>#include <cstdio>#include <cstdlib>#include <cmath>#include <deque>#include <limits>#include <iomanip>#include <ctype.h>#include <unordered_map>#include <random>#include <numeric>#include <iostream>#include <array>#include <atcoder/all>#define _USE_MATH_DEFINES#include <iostream>#include <fstream>#include <math.h>#include <bitset>#pragma intrinsic(_umul128)using namespace std;using namespace atcoder;typedef long long ll;typedef unsigned long long ull;typedef pair<int, int> pii;typedef pair<ll, ll> pll;typedef pair<ll, double> pld;typedef pair<double, double> pdd;typedef pair<double, ll> pdl;typedef pair<int, char> pic;typedef vector<ll> vl;typedef vector<pll> vpll;typedef vector<int> vi;typedef vector<string> table;typedef priority_queue<ll, vector<ll>, greater<ll>> llgreaterq;typedef priority_queue<pll, vector<pll>, greater<pll>> pllgreaterq;typedef priority_queue<pair<ll, pll>, vector<pair<ll, pll>>, greater<pair<ll, pll>>> plpllgreaterq;typedef priority_queue<vi, vector<vi>, greater<vi>> vigreaterq;typedef priority_queue<vl, vector<vl>, greater<vl >> vlgreaterq;typedef vector<vl> mat;typedef vector<mat> thd;template <class o, class p, class q>using tuple3q = priority_queue<tuple<o, p, q>, vector<tuple<o, p, q>>, greater<tuple<o, p, q>>>;template <class o, class p, class q, class r>using tuple4q = priority_queue<tuple<o, p, q, r>, vector<tuple<o, p, q, r>>, greater<tuple<o, p, q, r>>>;template <class o, class p, class q, class r, class s>using tuple5q = priority_queue<tuple<o, p, q, r, s>, vector<tuple<o, p, q, r, s>>, greater<tuple<o, p, q, r, s>>>;int dx[] = { -1,0,1,0 };int dy[] = { 0,1,0,-1 };int dxe[] = { 1,1,0,-1,-1,-1,0,1 };int dye[] = { 0,1,1,1,0,-1,-1,-1 };#define bit(x,v) ((ll)x << v)#define rep(x,n) for(ll x = 0;x < n;x++)#define rep2(x,f,v) for(ll x=f;x<v;x++)#define repe(v,x) for(auto v : x)// 許容する誤差ε#define EPS (1e-10)// 2つのスカラーが等しいかどうか#define EQ(a,b) (std::abs(a-b) < EPS)// 2つのベクトルが等しいかどうか#define EQV(a,b) ( EQ((a).real(), (b).real()) && EQ((a).imag(), (b).imag()) )#define all(a) a.begin(),a.end()#define all0(a) memset(a,0,sizeof(a))#define allm1(a) memset(a,-1,sizeof(a))#define set_float() cout << fixed << setprecision(12);#define coutl(s) cout <<s <<endl#define pln(s) cout<<s<<"\n"#define ple() pln(-1)#define plm(s) cout<<(s).val()<<"\n"#define plm17(s) cout<<modint1000000007(s).val()<<"\n"#define plm9(s) cout<<modint998244353(s).val()<<"\n"#define put_float(v) set_float() \pln(v)#define vinsert(v,p,x) v.insert(v.begin() + p,x)#define vsort(v) sort(all(v));#define vdesc(v) vsort(v); \reverse(all(v))#define dup(v) v.erase(unique(all(v)),v.end())#define ion(i,j) (i & (1LL << j))#define Len size()#define psp(a,b) push_back(make_pair(a,b))#define psp2(a,b) push(make_pair(a,b))#define cini(a) a; cin >> a#define infa(a,b) (a + b) % INF#define infm(a,b) (a * b) % INF#define infd(a,b) (a * INFinv(b)) % INF#define infs(a,b) (a + INF - inff(b)) % INF#define inf(a) (a) %= INF#define inff(a) ((a + INF) % INF)#define No cout << "No" << endl#define Yes cout << "Yes" << endl#define NO cout << "NO" << endl#define YES cout << "YES" << endl#define errm1 pln(-1);return;#define smal -(ll)1000000009*1000000009#define big (ll)1000000009*1000000009#define frontpop(q) q.front();q.pop()#define toppop(q) q.top();q.pop()#define arr(a,s) a[s]; all0(a);#define nxt(cu) (cu+1) % 2#define chkover(x,y,h,w) (x<0||y<0||x>=h||y>=w)#define psb(v) ll value;cin>>value;v.push_back(value);#define lower_b(v,p) lower_bound(all(v), p)#define upper_b(v,p) upper_bound(all(v), p)#define allpln(v) for(auto &e:v)pln(e)#define MIN(v) *min_element(all(v))#define MAX(v) *max_element(all(v))#define msize 216;#define revarr(p,l,r) reverse(p.begin()+l,p.begin()+r+1)#define reverse_all(p) reverse(all(p))#define cill(x) ll x;cin>>x#define cilll(x,y) ll x,y;cin>>x>>y#define bitn(x,k)(((x)>>(k))&1)template <typename T, typename U>T SUM(const vector<U>& A) {T sum = 0;for (auto&& a : A) sum += a;return sum;}ll n, m;bool chmin(ll& a, ll b) { if (a > b) { a = b; return 1; } return 0; }template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }ll INF = 1000000007;const int MAX = 3000010;void cout2(ll val) {if (val >= big) {pln(-1);}else {pln(val);}}void cout3(ll val) {if (val >= INF) {pln(-1);}else {pln(val);}}string padleft(string x, ll dig, char c) {ll si = x.size();for (ll i = 0; i < dig - si; i++){x = c + x;}return x;}long long fac[MAX], finv[MAX], inv[MAX], called;void COMinit() {fac[0] = fac[1] = 1;finv[0] = finv[1] = 1;inv[1] = 1;for (int i = 2; i < MAX; i++) {fac[i] = fac[i - 1] * i % INF;inv[i] = INF - inv[INF % i] * (INF / i) % INF;finv[i] = finv[i - 1] * inv[i] % INF;}}void COMinit998244353() {INF = 998244353;COMinit();called = 1;}void COMinit1000000007() {INF = 1000000007;COMinit();called = 1;}ll gfac(ll x) {if (!called) {COMinit();called = 1;}return fac[x];}// 二項係数計算long long COM(int n, int k) {if (!called) {COMinit();called = 1;}if (n < k) return 0;if (n < 0 || k < 0) return 0;return fac[n] * (finv[k] * finv[n - k] % INF) % INF;}modint998244353 COM2(ll n, ll k) {modint998244353 res = 1;rep(i, k) {res *= (n - i);res /= (i + 1);}return res;}ll getpow(ll b, ll x, ll md) {ll t = b % md;ll res = 1;while (x > 0){if (x & 1) {res *= t;res %= md;}x >>= 1;t *= t;t %= md;}return res % md;}ll getpow(ll b, ll x) {return getpow(b, x, INF);}/// 素数を法とする場合ll modinv(ll x) {return getpow(x, INF - 2);}ll extgcd(ll a, ll b, ll& x, ll& y) {ll d = a;if (b != 0) {d = extgcd(b, a % b, y, x);y -= (a / b) * x;}else {x = 1; y = 0;}return d;}/// <summary>/// 素数を法としない場合/// </summary>/// <param name="a"></param>/// <param name="m"></param>/// <returns></returns>ll modinv(ll a, ll m) {ll x, y;extgcd(a, m, x, y);return (m + x % m) % m;}ll gcd(ll a, ll b) {if (b == 0) return a;return gcd(b, a % b);}class m_random {std::mt19937 mt;std::uniform_int_distribution<> rand100;public:m_random(ll mi, ll ma) {init_random(mi, ma);}void init_random(ll mi, ll ma) {std::random_device rnd; // 非決定的な乱数生成器を生成mt = std::mt19937(rnd()); // メルセンヌ・ツイスタの32ビット版、引数は初期シード値rand100 = std::uniform_int_distribution<>(mi, ma);}ll get() {return rand100(mt);}};class m_sampling {std::mt19937 mt;std::normal_distribution<double> rand;public:m_sampling(double sigma) {init_sampling(sigma);}void init_sampling(double sigma) {std::random_device rnd;mt = std::mt19937(rnd());rand = std::normal_distribution<double>(0.0, sigma);}double get() {return rand(mt);}};class mint {public:long long x = 0;mint(ll x = 0) {this->x = (x % INF + INF) % INF;}mint operator-() const {return mint(-x);}mint& operator+=(const mint& a) {if ((x += a.x) >= INF) x -= INF;return *this;}mint& operator-=(const mint& a) {if ((x += INF - a.x) >= INF) x -= INF;return *this;}mint& operator*=(const mint& a) {(x *= a.x) %= INF;return *this;}mint operator+(const mint& a) const {mint res(*this);return res += a;}mint operator-(const mint& a) const {mint res(*this);return res -= a;}mint operator*(const mint& a) const {mint res(*this);return res *= a;}mint pow(ll t) const {if (!t) return 1;mint a = pow(t >> 1);a *= a;if (t & 1) a *= *this;return a;}// for prime INFmint inv() const {return pow(INF - 2LL);}mint& operator/=(const mint& a) {return (*this) *= a.inv();}mint operator/(const mint& a) const {mint res(*this);return res /= a;}friend ostream& operator<<(ostream& os, const mint& m) {os << m.x;return os;}};typedef vector<modint998244353> vml;typedef vector<vml> matm;typedef vector<modint1000000007> vml2;typedef vector<vml2> matm2;typedef vector<modint> vml3;typedef vector<vml3> matm3;// Union findvl pr;vl lank;vl udpt;void uini(int _n) {_n++; // 一個拡張しておくpr = vl(_n + 1);lank = vl(_n + 1);udpt = vl(_n + 1, 0);for (ll i = 0; i <= _n; i++){pr[i] = i;lank[i] = 1;}}int parent(int x) {if (x == pr[x]) return x;auto paren = parent(pr[x]);udpt[x] = udpt[paren] + 1;return pr[x] = paren;}int same(int x, int y) {return parent(x) == parent(y);}bool unit(int x, int y) {int px = parent(x);int py = parent(y);if (px == py) return false;if (lank[py] <= lank[px]) {pr[py] = px;lank[px] += lank[py];}else {pr[px] = py;lank[py] += lank[px];}return true;}ll unisize(ll i) {return lank[parent(i)];}bool unitm(int x, int y) {int px = parent(x);int py = parent(y);if (px == py) return false;if (lank[py] < lank[px]) {pr[py] = px;lank[px] += lank[py];}else {pr[px] = py;lank[py] += lank[px];}return true;}/// <summary>/// 数字の小さい方を親にするように処理/// </summary>/// <param name="x"></param>/// <param name="y"></param>/// <returns></returns>bool unitlow(int x, int y) {int px = parent(x);int py = parent(y);if (px == py) return false;if (py < px) {pr[py] = px;lank[px] += lank[py];}else {pr[px] = py;lank[py] += lank[px];}return true;}int H;int left(int i) {return i * 2 + 1;}int right(int i) {return i * 2 + 2;}class edge {public:int from, to, i;ll val;ll cap, rev, icap;edge() {}edge(ll to) : to(to) {}edge(ll to, ll i) : to(to), i(i) {}edge(ll from, ll to, ll val) : from(from), to(to), val(val) {}void flowEdge(ll _to, ll _cap, ll _rev) {to = _to;cap = _cap;icap = _cap;rev = _rev;}};typedef vector<vector<edge>> vve;class LCA {private:vector<vector<edge>> v;vector<vector<int>> parent;vector<int> depth;ll root;void dfs(int n, int m, int d) {parent[0][n] = m;depth[n] = d;for (auto x : v[n]) {if (x.to != m) dfs(x.to, n, d + 1);}}public:LCA() {}LCA(ll N, ll root, vector<vector<edge>>& tree) {v = tree;this->root = root;parent = vector<vector<int>>(21, vector<int>(N + 1, 0));depth = vector<int>(N + 1, 0);dfs(root, -1, 0);for (int j = 0; j + 1 < 20; j++) {for (int i = 1; i <= N; i++) {if (parent[j][i] < 0) parent[j + 1][i] = -1;else parent[j + 1][i] = parent[j][parent[j][i]];}}}int lca(int n, int m) {if (depth[n] > depth[m]) swap(n, m);if (n == root)return root;for (int j = 0; j < 20; j++) {if ((depth[m] - depth[n]) >> j & 1) m = parent[j][m];}if (n == m) return n;for (int j = 19; j >= 0; j--) {if (parent[j][n] != parent[j][m]) {n = parent[j][n];m = parent[j][m];}}return parent[0][n];}int dep(int n) { return depth[n]; }};ll k;int _rank[1010];int temp[1010];bool compare_sa(int i, int j) {if (_rank[i] != _rank[j]) return _rank[i] < _rank[j];else {int ri = i + k <= n ? _rank[i + k] : -1;int rj = j + k <= n ? _rank[j + k] : -1;return ri < rj;}}void construct_sa(string S, int* sa) {n = S.length();for (ll i = 0; i <= n; i++){sa[i] = i;_rank[i] = i < n ? S[i] : -1;}for (k = 1; k <= n; k *= 2){sort(sa, sa + n + 1, compare_sa);// saはソート後の接尾辞の並びになっている、rankは元の位置のindexを保持したまま、更新されている。// ピンとこなかった部分temp[sa[0]] = 0;for (ll i = 1; i <= n; i++){temp[sa[i]] = temp[sa[i - 1]] + (compare_sa(sa[i - 1], sa[i]) ? 1 : 0);}for (ll i = 0; i <= n; i++){_rank[i] = temp[i];}}}bool contain(string S, int* sa, string T) {int a = 0, b = S.length();// sa は 接尾辞が辞書順に並んでいる、入っているのはその位置のインデックスwhile (b - a > 1) {int c = (a + b) / 2;if (S.compare(sa[c], T.length(), T) < 0) a = c;else b = c;}return S.compare(sa[b], T.length(), T) == 0;}#define bit(x,v) ((ll)x << v)class BIT {static const int MAX_N = 500010;public:vl bit;ll n;BIT() { bit = vl(MAX_N + 1, 0); }BIT(ll _n) {bit = vl(_n * 2 + 10, 0);n = _n;}ll sum(int i) {ll s = 0;while (i > 0){s += bit[i];i -= i & -i;}return s;}void add(int i, int x) {while (i <= n){bit[i] += x;i += i & -i;}}};struct UnionFind {vector<int> A;UnionFind(int n) : A(n, -1) {}int find(int x) {if (A[x] < 0) return x;return A[x] = find(A[x]);}void unite(int x, int y) {x = find(x), y = find(y);if (x == y) return;if (A[x] > A[y]) swap(x, y);A[x] += A[y];A[y] = x;}int ngroups() {int ans = 0;for (auto a : A) if (a < 0) ans++;return ans;}};vector<ll> getp(ll n) {vector<ll> res;if (n % 2 == 0) {res.push_back(2);while (n % 2 == 0)n /= 2;}for (ll i = 3; i * i <= n; i += 2){if (n % i == 0) {res.push_back(i);while (n % i == 0)n /= i;}}if (n != 1) res.push_back(n);return res;}vector<ll> getpp(ll n) {vector<ll> res;if (n % 2 == 0) {res.push_back(2);while (n % 2 == 0)n /= 2;}for (ll i = 3; i * i * i <= n; i += 2){if (n % i == 0) {res.push_back(i);while (n % i == 0)n /= i;}}if (n != 1) res.push_back(n);return res;}vector<ll> getp2(ll n) {vector<ll> res;if (n % 2 == 0) {while (n % 2 == 0) { n /= 2; res.push_back(2); }}for (ll i = 3; i * i <= n; i += 2){if (n % i == 0) {while (n % i == 0) { n /= i; res.push_back(i); }}}if (n != 1) res.push_back(n);return res;}vector<pll> getp3(ll n) {vector<pll> res;int si = 0;if (n % 2 == 0) {res.push_back(make_pair(2, 0));while (n % 2 == 0) { n /= 2; res[si].second++; }si++;}for (ll i = 3; i * i <= n; i += 2){if (n % i == 0) {res.push_back(make_pair(i, 0));while (n % i == 0) { n /= i; res[si].second++; }si++;}}if (n != 1) { res.push_back(make_pair(n, 1)); }return res;}vector<ll> getDivisors(ll n) {vector<ll> res;res.push_back(1);if (1 < n)res.push_back(n);for (ll i = 2; i * i <= n; i++){if (n % i == 0) {res.push_back(i);if (n / i != i)res.push_back(n / i);}}vsort(res);return res;}struct ve {public:vector<ve> child;int _t = INF;ve(int t) :_t(t) {}ve(ve _left, ve _right) {_t = _left._t + _right._t;child.push_back(_left);child.push_back(_right);}bool operator<(const ve& t) const {return _t > t._t;}};vector<bool> elas(ll n) {n++;vector<bool> r(n, 1);r[0] = 0;r[1] = 0;ll tw = 4;while (tw < n) {r[tw] = false;tw += 2;}ll th = 6;while (th < n) {r[th] = false;th += 3;}ll fv = 10;while (fv < n) {r[fv] = false;fv += 5;}for (ll i = 6; i * i < n; i += 6){ll bf = i - 1;if (r[bf]) {ll ti = bf * 2;while (ti < n){r[ti] = false;ti += bf;}}ll nx = i + 1;if (r[nx]) {ll ti = nx * 2;while (ti < n){r[ti] = false;ti += nx;}}}return r;}vl getprimes(ll x) {auto e = elas(x);vl r;rep2(i, 2, x + 1) {if (e[i])r.push_back(i);}return r;}bool isPrime(ll v) {if (v == 1 || v == 0)return false;for (ll i = 2; i * i <= v; i++){if (v % i == 0) return false;}return true;}class SegTree {public:const static int MAX_N = 1000100;const static int DAT_SIZE = (1 << 20) - 1;int N, Q;int A[MAX_N];ll MAX = big;ll data[DAT_SIZE], datb[DAT_SIZE];void init(int _n) {N = 1;while (N < _n) N <<= 1;memset(data, 0, sizeof(data));memset(datb, 0, sizeof(datb));}void init(int _n, ll iv) {N = 1;while (N < _n) N <<= 1;rep(i, DAT_SIZE) {data[i] = iv;datb[i] = iv;}}void initRMQ(int _n) {N = 1;while (N < _n) N *= 2;// 全ての値をbigにrep(i, 2 * N - 1)data[i] = MAX;}void updateRMQ(int k, ll a) {k += N - 1;data[k] = a;while (k > 0) {k = (k - 1) / 2;data[k] = min(data[k * 2 + 1], data[k * 2 + 2]);}}ll RMQ(int a, int b) {return queryRMQ(a, b + 1, 0, 0, N);}ll queryRMQ(int a, int b, int k, int l, int r) {if (r <= a || b <= l)return MAX;// [a,b)が[l,r)を完全に含んでいればif (a <= l && r <= b)return data[k];// そうでなければ2つの子の最小値// n=16// 0,16→0,8 8,16// 0,4 4,8 8,12 12,16ll vl = queryRMQ(a, b, k * 2 + 1, l, (l + r) / 2);ll vr = queryRMQ(a, b, k * 2 + 2, (l + r) / 2, r);return min(vl, vr);}void add(int a, int b, int x) {add(a, b + 1, x, 0, 0, N);}void add(int a, int b, int x, int k, int l, int r) {if (a <= l && r <= b) {data[k] += x;}else if (l < b && a < r) {datb[k] += (min(b, r) - max(a, l)) * x;add(a, b, x, k * 2 + 1, l, (l + r) / 2);add(a, b, x, k * 2 + 2, (l + r) / 2, r);}}void change(int a, int b, int x) {change(a, b + 1, x, 0, 0, N);}void change(int a, int b, int x, int k, int l, int r) {if (a <= l && r <= b) {data[k] = x;}else if (l < b && a < r) {datb[k] = x;change(a, b, x, k * 2 + 1, l, (l + r) / 2);change(a, b, x, k * 2 + 2, (l + r) / 2, r);}}ll sum(int a, int b) {return sum(a, b + 1, 0, 0, N);}ll sum(int a, int b, int k, int l, int r) {if (b <= l || r <= a) {return 0;}if (a <= l && r <= b) {return data[k] * (r - l) + datb[k];}ll res = (min(b, r) - max(a, l)) * data[k];res += sum(a, b, k * 2 + 1, l, (l + r) / 2);res += sum(a, b, k * 2 + 2, (l + r) / 2, r);return res;}};class LazySegTree {private:int N;vl node, lazy;public:void init(int _n) {N = 1;while (N < _n) N <<= 1;node.resize(2 * N, 0);lazy.resize(2 * N, 0);}// k 番目のノードについて遅延評価を行うvoid eval(int k, int l, int r) {// 遅延配列が空でない場合、自ノード及び子ノードへの// 値の伝播が起こるif (lazy[k] != 0) {node[k] += lazy[k];// 最下段かどうかのチェックをしよう// 子ノードは親ノードの 1/2 の範囲であるため、// 伝播させるときは半分にするif (r - l > 1) {lazy[2 * k + 1] += lazy[k] / 2;lazy[2 * k + 2] += lazy[k] / 2;}// 伝播が終わったので、自ノードの遅延配列を空にするlazy[k] = 0;}}void add(int a, int b, ll x) {addbody(a, b + 1, x);}void addbody(int a, int b, ll x, int k = 0, int l = 0, int r = -1) {if (r < 0) r = N;// k 番目のノードに対して遅延評価を行うeval(k, l, r);// 範囲外なら何もしないif (b <= l || r <= a) return;// 完全に被覆しているならば、遅延配列に値を入れた後に評価if (a <= l && r <= b) {lazy[k] += (r - l) * x;eval(k, l, r);}// そうでないならば、子ノードの値を再帰的に計算して、// 計算済みの値をもらってくるelse {addbody(a, b, x, 2 * k + 1, l, (l + r) / 2);addbody(a, b, x, 2 * k + 2, (l + r) / 2, r);node[k] = node[2 * k + 1] + node[2 * k + 2];}}ll getsum(int a, int b, int k = 0, int l = 0, int r = -1) {if (r < 0) r = N;if (b <= l || r <= a) return 0;// 関数が呼び出されたら評価!eval(k, l, r);if (a <= l && r <= b) return node[k];ll vl = getsum(a, b, 2 * k + 1, l, (l + r) / 2);ll vr = getsum(a, b, 2 * k + 2, (l + r) / 2, r);return vl + vr;}ll getMax(int a, int b) {// 半開区間に変換return getMaxBdy(a, b + 1);}ll getMaxBdy(int a, int b, int k = 0, int l = 0, int r = -1) {if (r < 0) r = N;if (b <= l || r <= a) return -big;// 関数が呼び出されたら評価!eval(k, l, r);if (a <= l && r <= b) return node[k];ll vl = getMaxBdy(a, b, 2 * k + 1, l, (l + r) / 2);ll vr = getMaxBdy(a, b, 2 * k + 2, (l + r) / 2, r);return max(vl, vr);}};class LazySegTreeRMQ {private:int N;vl node, lazy;public:void init(int _n) {N = 1;while (N < _n) N <<= 1;node.resize(2 * N, 0);lazy.resize(2 * N, 0);}// k 番目のノードについて遅延評価を行うvoid eval(int k, int l, int r) {if (lazy[k] != 0) {node[k] = lazy[k];if (r - l > 1) {lazy[2 * k + 1] = lazy[k];lazy[2 * k + 2] = lazy[k];}lazy[k] = 0;}}void evalAdd(int k, int l, int r) {if (lazy[k] != 0) {node[k] += lazy[k];if (r - l > 1) {lazy[2 * k + 1] += lazy[k];lazy[2 * k + 2] += lazy[k];}lazy[k] = 0;}}void add(int a, int b, ll x) {addbody(a, b + 1, x);}void addbody(int a, int b, ll x, int k = 0, int l = 0, int r = -1) {if (r < 0) r = N;// k 番目のノードに対して遅延評価を行うevalAdd(k, l, r);// 範囲外なら何もしないif (b <= l || r <= a) return;// 完全に被覆しているならば、遅延配列に値を入れた後に評価if (a <= l && r <= b) {lazy[k] += x;evalAdd(k, l, r);}// そうでないならば、子ノードの値を再帰的に計算して、// 計算済みの値をもらってくるelse {addbody(a, b, x, 2 * k + 1, l, (l + r) / 2);addbody(a, b, x, 2 * k + 2, (l + r) / 2, r);node[k] = max(node[2 * k + 1], node[2 * k + 2]);}}void update(int a, int b, ll v) {updateBdy(a, b + 1, v);}void updateBdy(int a, int b, ll x, int k = 0, int l = 0, int r = -1) {if (r < 0) r = N;// k 番目のノードに対して遅延評価を行うeval(k, l, r);// 範囲外なら何もしないif (b <= l || r <= a) return;// 完全に被覆しているならば、遅延配列に値を入れた後に評価if (a <= l && r <= b) {if (x > node[k]) {lazy[k] = x;eval(k, l, r);}}// そうでないならば、子ノードの値を再帰的に計算して、// 計算済みの値をもらってくるelse {updateBdy(a, b, x, 2 * k + 1, l, (l + r) / 2);updateBdy(a, b, x, 2 * k + 2, (l + r) / 2, r);node[k] = max(node[2 * k + 1], node[2 * k + 2]);}}ll getMaxAdd(int a, int b) {// 半開区間に変換return getMaxAddBdy(a, b + 1);}ll getMaxAddBdy(int a, int b, int k = 0, int l = 0, int r = -1) {if (r < 0) r = N;if (b <= l || r <= a) return -big;// 関数が呼び出されたら評価!evalAdd(k, l, r);if (a <= l && r <= b) return node[k];ll vl = getMaxAddBdy(a, b, 2 * k + 1, l, (l + r) / 2);ll vr = getMaxAddBdy(a, b, 2 * k + 2, (l + r) / 2, r);return max(vl, vr);}ll getMax(int a, int b) {// 半開区間に変換return getMaxBdy(a, b + 1);}ll getMaxBdy(int a, int b, int k = 0, int l = 0, int r = -1) {if (r < 0) r = N;if (b <= l || r <= a) return -big;// 関数が呼び出されたら評価!eval(k, l, r);if (a <= l && r <= b) return node[k];ll vl = getMaxBdy(a, b, 2 * k + 1, l, (l + r) / 2);ll vr = getMaxBdy(a, b, 2 * k + 2, (l + r) / 2, r);return max(vl, vr);}};class Segment;class Circle;class Point {public:double x, y;Point(double x = 0, double y = 0) :x(x), y(y) {}Point operator + (Point p) { return Point(x + p.x, y + p.y); }Point operator - (Point p) { return Point(x - p.x, y - p.y); }Point operator * (double a) { return Point(a * x, a * y); }Point operator / (double a) { return Point(x / a, y / a); }double abs() { return sqrt(norm()); }double norm() { return x * x + y * y; }bool operator < (const Point& p)const {return x != p.x ? x < p.x : y < p.y;}bool operator == (const Point& p) const {return fabs(x - p.x) < EPS && fabs(y - p.y) < EPS;}// 内積static double dot(Point a, Point b) {return a.x * b.x + a.y * b.y;}// 外積static double cross(Point a, Point b) {return a.x * b.y - a.y * b.x;}static bool isOrthogonal(Point a, Point b) {return EQ(dot(a, b), 0.0);}static bool isOrthogonal(Point a1, Point a2, Point b1, Point b2) {return isOrthogonal(a1 - a2, b1 - b2);}static bool isOrthogonal(Segment s1, Segment s2);static bool isPalallel(Point a, Point b) {return EQ(cross(a, b), 0.0);}static bool isPalallel(Point a1, Point a2, Point b1, Point b2) {return isPalallel(a1 - a2, b1 - b2);}static bool isPalallel(Segment s1, Segment s2);static const int COUNTER_CLOCKWISE = 1;static const int CLOCKWISE = -1;static const int ONLINE_BACK = 2;static const int ONLINE_FRONT = -2;static const int ON_SEGMENT = 0;static int ccw(Point p0, Point p1, Point p2) {// 線分はp0とp1でp2がどこにあるかを探るPoint a = p1 - p0;Point b = p2 - p0;if (cross(a, b) > EPS) return COUNTER_CLOCKWISE;if (cross(a, b) < -EPS) return CLOCKWISE;if (dot(a, b) < -EPS) return ONLINE_BACK;if (a.norm() < b.norm()) return ONLINE_FRONT;return ON_SEGMENT;}// 交差しているかstatic bool intersect(Point p1, Point p2, Point p3, Point p4) {return (ccw(p1, p2, p3) * ccw(p1, p2, p4) <= 0&& ccw(p3, p4, p1) * ccw(p3, p4, p2) <= 0);}static bool intersect(Segment s1, Segment s2);static Point project(Segment s, Point p);static Point reflect(Segment s, Point p);static Point getDistance(Point a, Point b) {return (a - b).abs();}static double getDistanceLP(Segment s, Point p);static double getDistanceSP(Segment s, Point p);static double getDistance(Segment s1, Segment s2);static Point getIntersection(Segment s1, Segment s2);static pair<Point, Point> crossPoints(Circle c, Segment s);static int contains(vector<Point> g, Point p) {int n = g.size();bool x = false;rep(i, n) {Point a = g[i] - p, b = g[(i + 1) % n] - p;// 線の上に載っているかif (std::abs(cross(a, b)) < EPS && dot(a, b) < EPS) return 1;// pを基準として上下にあるか// または外積が正か?(→にあるか)if (a.y > b.y) swap(a, b);if (a.y < EPS && EPS < b.y && cross(a, b) > EPS) x = !x;}return x ? 2 : 0;}static vector<Point> andrewScan(vector<Point> s) {vector<Point> u, l;ll si = s.size();if (si < 3) return s;sort(all(s));u.push_back(s[0]);u.push_back(s[1]);l.push_back(s[si - 1]);l.push_back(s[si - 2]);for (int i = 2; i < si; i++) {for (int _n = u.size(); _n >= 2 && ccw(u[_n - 2], u[_n - 1], s[i]) > CLOCKWISE; _n--) {u.pop_back();}u.push_back(s[i]);}for (int i = s.size() - 3; i >= 0; i--) {for (int _n = l.size(); _n >= 2 && ccw(l[_n - 2], l[_n - 1], s[i]) > CLOCKWISE; _n--) {l.pop_back();}l.push_back(s[i]);}reverse(all(l));for (int i = u.size() - 2; i >= 1; i--){l.push_back(u[i]);}return l;}void get_cin() {cin >> x >> y;}static Point rotate(double r, Point p) {Point ret;ret.x = cos(r) * p.x - sin(r) * p.y;ret.y = sin(r) * p.x + cos(r) * p.y;return ret;}};class Segment {public:Point p1, p2;Segment() {}Segment(Point p1, Point p2) :p1(p1), p2(p2) {}void get_cin() {cin >> p1.x >> p1.y >> p2.x >> p2.y;}Point p1tp2() {return p2 - p1;}Point p2tp1() {return p1 - p2;}double abs() {return (p2 - p1).abs();}double norm() {return (p2 - p1).norm();}};// 直行bool Point::isOrthogonal(Segment s1, Segment s2) {return EQ(dot(s1.p2 - s1.p1, s2.p2 - s2.p1), 0.0);}// 平行bool Point::isPalallel(Segment s1, Segment s2) {return EQ(cross(s1.p2 - s1.p1, s2.p2 - s2.p1), 0.0);}// 交差しているかbool Point::intersect(Segment s1, Segment s2) {return intersect(s1.p1, s1.p2, s2.p1, s2.p2);}Point Point::project(Segment s, Point p) {Point base = s.p2 - s.p1;double r = Point::dot(p - s.p1, base) / base.norm();return s.p1 + base * r;}Point Point::reflect(Segment s, Point p) {return (project(s, p) * 2) - p;}double Point::getDistanceLP(Segment s, Point p) {return std::abs(cross(s.p2 - s.p1, p - s.p1) / (s.p2 - s.p1).abs());}double Point::getDistanceSP(Segment s, Point p) {if (dot(s.p2 - s.p1, p - s.p1) < 0.0) return (p - s.p1).abs();if (dot(s.p1 - s.p2, p - s.p2) < 0.0) return (p - s.p2).abs();return getDistanceLP(s, p);}double Point::getDistance(Segment s1, Segment s2) {if (intersect(s1, s2)) return 0.0;return min({ getDistanceSP(s1,s2.p1),getDistanceSP(s1,s2.p2),getDistanceSP(s2,s1.p1),getDistanceSP(s2,s1.p2) });}Point Point::getIntersection(Segment s1, Segment s2) {// (s1.p1 - s2.p1).norm()auto bs = s1.p2 - s1.p1;auto n1 = s2.p1 - s1.p1;auto n2 = s2.p2 - s1.p1;auto c1 = std::abs(cross(n1, bs)) / bs.norm();auto c2 = std::abs(cross(n2, bs)) / bs.norm();return s2.p1 + (s2.p2 - s2.p1) * (c1 / (c1 + c2));// c1:c2=t:1-t// c2t=(1-t)c1// t/(1-t)=c1/(c1+c2)//}double arg(Point p) { return atan2(p.y, p.x); }Point polar(double a, double r) { return Point(cos(r) * a, sin(r) * a); }class Circle {public:Point c;double r;Circle(Point c = Point(), double r = 0.0) : c(c), r(r) {}void get_cin() {cin >> c.x >> c.y >> r;}static pair<Point, Point> getCrossPoints(Circle c1, Circle c2) {double d = (c1.c - c2.c).abs(); // 中心点どうしの距離double a = acos((c1.r * c1.r + d * d - c2.r * c2.r) / (2 * c1.r * d));double t = arg(c2.c - c1.c);return make_pair(c1.c + polar(c1.r, t + a), c1.c + polar(c1.r, t - a));}};pair<Point, Point> Point::crossPoints(Circle c, Segment s) {auto pp = project(s, c.c);auto f = (pp - c.c).norm();auto mu = sqrt(c.r * c.r - f);// 単位ベクトルauto e = s.p1tp2() / s.p1tp2().abs();return make_pair(pp + e * mu, pp - e * mu);}ll divRm(string s, ll x) {ll r = 0;for (ll i = 0; i < s.size(); i++){r *= 10;r += s[i] - '0';r %= x;}return r;}ll cmbi(ll x, ll b) {ll res = 1;for (size_t i = 0; i < b; i++){res *= x - i;res %= INF;res *= inv[b - i];res %= INF;}return res;}map<ll, ll> dgmemo;ll digsum(ll x) {if (dgmemo.count(x))return dgmemo[x];ll res = 0;while (x > 0){res += x % 10;x /= 10;}return res;}bool check_parindrome(string s) {int n = s.size();rep(i, n / 2) {if (s[i] != s[n - i - 1]) {return false;}}return true;}ll npr(ll n, ll r) {if (r == 0)return 1;return inff(fac[n] * modinv(fac[n - r]));}vl zalgo(string s) {ll c = 0;vl a(s.size());ll si = s.size();rep2(i, 1, s.size()) {if (i + a[i - c] < c + a[c]){a[i] = a[i - c];}else {ll j = max(0LL, a[c] - (i - c));while (i + j < si && s[j] == s[i + j]){j++;}a[i] = j;c = i;}}a[0] = s.size();return a;}// 数値文字列の除算string divStrNum(string s, ll v) {ll si = s.size();ll val = 0;string res = "";for (ll i = 0; i < si; i++){val *= 10;val += s[i] - '0';ll add = val / v;val %= v;if (add == 0 && res == "")continue;res += add + '0';}if (res == "")return "0";return res;}// 数値文字列の減算string difStrNum(string s, ll v) {ll si = s.size();bool dec = false;for (ll i = si - 1; i >= 0; i--){if (v == 0)break;ll t = v % 10;v /= 10;ll u = (s[i] - '0');if (dec) {if (u == 0) {s[i] = 9 - t;dec = true;continue;}u--;}if (u < t) {s[i] = 10 - (t - u);dec = true;}else {s[i] -= t;dec = false;}}return s;}// 数値文字列を1減らした数string decStrNum(string s) {ll si = s.size();for (int i = si - 1; i >= 0; i--){if (s[i] == '0') {s[i] = '9';continue;}s[i] = s[i] - 1;break;}return s;}void dateCal(int x) {int lp = x / 7;string date[] = { "月曜日","火曜日","水曜日","木曜日","金曜日","土曜日","日曜日" };rep(i, 7) {int st = i;rep(j, lp) {cout << "\t" << date[i] << x << "-" << st << "\t" << "NULL" << "\t" << x << "\t" << st << "\t" << 0 << endl;st += 7;}}}// 行列べき乗計算mat mul(mat& A, mat& B) {ll as = A.size();ll bs = B.size();mat C(A.size(), vl(B[0].size()));rep(i, as) {rep(t, bs) {ll bz = B[0].size();rep(j, bz) {C[i][j] = inff(C[i][j] + A[i][t] * B[t][j]);}}}return C;}mat pow(mat A, ll x) {if (A.size() == 0)return A;mat B(A.size(), vl(A.size()));rep(i, A.size()) {B[i][i] = 1;}while (x > 0){if (x & 1)B = mul(B, A);A = mul(A, A);x >>= 1;}return B;}class dinic {public:vve G;vl level;vl iter;dinic(int _n) : dinic(vve(_n + 1)) {}dinic(vve g) {G = g;level = vl(g.size());iter = vl(g.size());}void add_edge(ll from, ll to, ll cap) {auto e1 = edge();auto e2 = edge();e1.flowEdge(to, cap, G[to].size());G[from].push_back(e1);e2.flowEdge(from, 0, G[from].size() - 1);G[to].push_back(e2);}void bfs(ll s) {fill(all(level), -1);queue<ll> q;level[s] = 0;q.push(s);while (!q.empty()){ll v = frontpop(q);for (auto e : G[v]) {if (e.cap > 0 && level[e.to] < 0) {level[e.to] = level[v] + 1;q.push(e.to);}}}}ll dfs(ll v, ll t, ll f) {if (v == t)return f;for (ll& i = iter[v]; i < G[v].size(); i++) {edge& e = G[v][i];if (e.cap > 0 && level[v] < level[e.to]) {ll d = dfs(e.to, t, min(f, e.cap));if (d > 0) {e.cap -= d;G[e.to][e.rev].cap += d;return d;}}}return 0;}ll max_flow(ll s, ll t) {ll flow = 0;for (;;) {bfs(s);if (level[t] < 0)return flow;fill(all(iter), 0);ll f;while ((f = dfs(s, t, big)) > 0){flow += f;}}}};const ull BS = 1000000007;// aはbに含まれているか?bool rolling_hash(string a, string b) {int al = a.size(), bl = b.size();if (al > bl)return false;// BSのal乗を計算ull t = 1;rep(i, al)t *= BS;// aとbの最初のal文字に関するハッシュ値を計算ull ah = 0, bh = 0;rep(i, al) ah = ah * BS + a[i];rep(i, al) bh = bh * BS + b[i];// bの場所を一つずつ進めながらハッシュ値をチェックfor (ll i = 0; i + al <= bl; i++){if (ah == bh)return true;if (i + al < bl)bh = bh * BS + b[i + al] - b[i] * t;}return false;}mat sans(9, vl(9, -1));bool srec(ll x, ll y) {if (x == 9)return true;vl use(10, 0);rep(i, 9) {if (sans[i][y] == -1)continue;use[sans[i][y]] = 1;}rep(j, 9) {if (sans[x][j] == -1)continue;use[sans[x][j]] = 1;}ll px = x % 3;ll py = y % 3;ll tx = x - px + 3;ll ty = y - py + 3;rep2(i, x - px, tx) {rep2(j, y - py, ty) {if (sans[i][j] == -1)continue;use[sans[i][j]] = 1;}}ll nx, ny;if (y == 8) {nx = x + 1;ny = 0;}else {nx = x;ny = y + 1;}if (sans[x][y] != -1) {if (srec(nx, ny)) {return true;}return false;}rep2(i, 1, 10) {if (use[i])continue;sans[x][y] = i;if (srec(nx, ny)) {return true;}sans[x][y] = -1;}return false;}void sudoku() {vector<string> tb;rep(i, 9) {string s;cin >> s;tb.push_back(s);rep(j, 9) {if (tb[i][j] != '.') {sans[i][j] = tb[i][j] - '0';}}}srec(0, 0);rep(i, 9) {rep(j, 9) {cout << sans[i][j];}cout << endl;}}mint ncr(ll n, ll r) {mint v = 1;rep(i, r) {v *= (n - i);v *= inv[i + 1];}return v;}modint1000000007 ncr2(ll n, ll r) {modint1000000007 v = 1;rep(i, r) {v *= (n - i);v /= i + 1;}return v;}ll sq(ll x) {return x * x;}ll phi(ll x) {auto p = getp(x);ll res = x;for (auto v : p) {res /= v;res *= v - 1;}return res;}const ull MASK30 = (1ULL << 30) - 1;const ull MASK31 = (1ULL << 31) - 1;const ull MOD = (1ULL << 61UL) - 1UL;const ull MASK61 = MOD;//mod 2^61-1を計算する関数ull calc_mod_61(ull x){ull xu = x >> 61;ull xd = x & MASK61;ull res = xu + xd;if (res >= MOD) res -= MOD;return res;}ull mul_61(ull a, ull b){ull au = a >> 31;ull ad = a & MASK31;ull bu = b >> 31;ull bd = b & MASK31;ull mid = ad * bu + au * bd;ull midu = mid >> 30;ull midd = mid & MASK30;return calc_mod_61(au * bu * 2 + midu + (midd << 31) + ad * bd);}vl mulMatVec(mat a, vl b){int n = b.size(); vl ret(n, 0);rep(i, n) rep(j, n)ret[j] = inff(ret[j] + inff(a[i][j] * b[i]));return ret;}ll isqrt(ll N) {ll sqrtN = sqrt(N) - 1;while (sqrtN + 1 <= N / (sqrtN + 1))sqrtN++;return sqrtN;}ll cross(pll l, pll r) {return l.first * r.second - l.second * r.first;}void rotate(vl& v) {v.push_back(v.front());v.erase(v.begin());}class ConvexHullDynamic{typedef long long coef_t;typedef long long coord_t;typedef long long val_t;/** Line 'y=a*x+b' represented by 2 coefficients 'a' and 'b'* and 'xLeft' which is intersection with previous line in hull(first line has -INF)*/private:struct Line{coef_t a, b;double xLeft;enum Type{line, maxQuery, minQuery} type;coord_t val;explicit Line(coef_t aa = 0, coef_t bb = 0) : a(aa), b(bb), xLeft(-INFINITY), type(Type::line), val(0) {}val_t valueAt(coord_t x) const { return a * x + b; }friend bool areParallel(const Line& l1, const Line& l2) { return l1.a == l2.a; }friend double intersectX(const Line& l1, const Line& l2) { return areParallel(l1, l2) ? INFINITY : 1.0 * (l2.b - l1.b) / (l1.a - l2.a); }bool operator<(const Line& l2) const{if (this->type == maxQuery)return this->val < l2.xLeft;if (this->type == minQuery)return this->val > l2.xLeft;if (l2.type == line)return this->a < l2.a;if (l2.type == maxQuery)return this->xLeft < l2.val;if (l2.type == minQuery)return this->xLeft > l2.val;}};bool isMax; //whether or not saved envelope is top(search of max value)public:std::set< Line > hull; //envelope itselfprivate:/** INFO: Check position in hull by iterator* COMPLEXITY: O(1)*/bool hasPrev(std::set< Line >::iterator it) { return it != hull.begin(); }bool hasNext(std::set< Line >::iterator it) { return it != hull.end() && std::next(it) != hull.end(); }/** INFO: Check whether line l2 is irrelevant* NOTE: Following positioning in hull must be true* l1 is next left to l2* l2 is right between l1 and l3* l3 is next right to l2* COMPLEXITY: O(1)*/bool irrelevant(const Line& l1, const Line& l2, const Line& l3) { return intersectX(l1, l3) <= intersectX(l1, l2); }bool irrelevant(std::set< Line >::iterator it){return hasPrev(it) && hasNext(it)&& (isMax && irrelevant(*std::prev(it), *it, *std::next(it))|| !isMax && irrelevant(*std::next(it), *it, *std::prev(it)));}/** INFO: Updates 'xValue' of line pointed by iterator 'it'* COMPLEXITY: O(1)*/std::set< Line >::iterator updateLeftBorder(std::set< Line >::iterator it){if (isMax && !hasPrev(it) || !isMax && !hasNext(it))return it;double val = intersectX(*it, isMax ? *std::prev(it) : *std::next(it));Line buf(*it);it = hull.erase(it);buf.xLeft = val;it = hull.insert(it, buf);return it;}public:explicit ConvexHullDynamic(bool isMax = false) : isMax(isMax) {}/** INFO: Adding line to the envelope* Line is of type 'y=a*x+b' represented by 2 coefficients 'a' and 'b'* COMPLEXITY: Adding N lines(N calls of function) takes O(N*log N) time*/void addLine(coef_t a, coef_t b){//find the place where line will be inserted in setLine l3 = Line(a, b);auto it = hull.lower_bound(l3);//if parallel line is already in set, one of them becomes irrelevantif (it != hull.end() && areParallel(*it, l3)) {if (isMax && it->b < b || !isMax && it->b > b)it = hull.erase(it);elsereturn;}//try to insertit = hull.insert(it, l3);if (irrelevant(it)) {hull.erase(it);return;}//remove lines which became irrelevant after inserting linewhile (hasPrev(it) && irrelevant(std::prev(it))) hull.erase(std::prev(it));while (hasNext(it) && irrelevant(std::next(it))) hull.erase(std::next(it));//refresh 'xLine'it = updateLeftBorder(it);if (hasPrev(it))updateLeftBorder(std::prev(it));if (hasNext(it))updateLeftBorder(std::next(it));}val_t getBest(coord_t x) const{Line q;q.val = x;q.type = isMax ? Line::Type::maxQuery : Line::Type::minQuery;auto bestLine = hull.lower_bound(q);if (isMax) --bestLine;return bestLine->valueAt(x);}};class treelib {public:mat es;vl stop;vl d;treelib(mat _es) : es(_es) {stop.resize(_es.size() + 1, 0);d.resize(_es.size() + 1);}/** first: depth.second : leaf;*/pll deepest(ll x, ll f) {ll a = 0, b = -1;for (auto v : es[x]) {if (stop[v])continue;if (v == f)continue;d[v] = d[x] + 1;auto p = deepest(v, x);if (p.first > a) {a = p.first;b = p.second;}}if (b == -1) {return { 1,x };}else {return { a + 1,b };}}};pair<vl, map<ll, ll>> compress(vl& v) {ll n = v.size();vl b(n);rep(i, n) {b[i] = v[i];}vsort(b);dup(b);map<ll, ll> mp;rep(i, b.size()) {mp[b[i]] = i;}vl res(n);rep(i, n) {res[i] = mp[v[i]];}return { res,mp };}using ld = double;using P = Point;template <class iter>Circle min_ball(iter left, iter right, int seed = 1333) {const int n = right - left;assert(n >= 1);if (n == 1) {return { *left, ld(0) };}std::mt19937 mt(seed);std::shuffle(left, right, mt);// std::random_shuffle(left, right); // simple but deprecatediter ps = left;using circle = Circle;auto make_circle_3 = [](P& a, P& b, P& c) -> circle {ld A = (b - c).norm(), B = (c - a).norm(), C = (a - b).norm(),S = Point::cross(b - a, c - a);P p = (a * (A * (B + C - A)) + (b * B * (C + A - B)) + c * C * (A + B - C))/ (4 * S * S);ld r2 = (p - a).norm();return { p, r2 };};auto make_circle_2 = [](P& a, P& b) -> circle {P c = (a + b) / (ld)2;ld r2 = (a - c).norm();return { c, r2 };};auto in_circle = [](P& a, circle& c) -> bool {return (a - c.c).norm() <= c.r + EPS;};circle c = make_circle_2(ps[0], ps[1]);// MiniDiscfor (int i = 2; i < n; ++i) {if (!in_circle(ps[i], c)) {// MiniDiscWithPointc = make_circle_2(ps[0], ps[i]);for (int j = 1; j < i; ++j) {if (!in_circle(ps[j], c)) {// MiniDiscWith2Pointsc = make_circle_2(ps[i], ps[j]);for (int k = 0; k < j; ++k) {if (!in_circle(ps[k], c)) {c = make_circle_3(ps[i], ps[j], ps[k]);}}}}}}return c;}vml2 kitamasadfs(vml2 a, vml2 d, ll n) {if (d.size() == n)return d;vml2 res(d.size());if (n < d.size() * 2 || (n & 1)) {auto f = kitamasadfs(a, d, n - 1);res[0] = f[k - 1] * d[0];rep2(i, 1, d.size()) {res[i] = f[i - 1] + f[k - 1] * d[i];}}else {auto v = kitamasadfs(a, d, n / 2);matm2 f(d.size(), vml2(d.size()));f[0] = v;rep2(i, 1, d.size()) {f[i][0] = f[i - 1][k - 1] * d[0];rep2(j, 1, d.size()) {f[i][j] = f[i - 1][j - 1] + f[i - 1][k - 1] * d[j];}}rep(i, d.size()) {rep(j, d.size()) {res[j] += f[i][j] * v[i];}}}return res;}modint1000000007 kitamasa(vml2 a, vml2 d, ll n) {auto v = kitamasadfs(a, d, n);modint1000000007 res = 0;rep(i, d.size()) {res += v[i] * a[i];}return res;}void belman_temp(vector<vpll>& es, vl& d, ll s) {d[s] = 0;rep(i, n + 1) {queue<ll> q;rep2(j, 1, n + 1) {if (d[j] == big)continue;for (auto& v : es[j]) {if (chmin(d[v.first], d[j] + v.second)) {q.push(v.first);}}}if (i < n)continue;while (!q.empty()){auto p = frontpop(q);for (auto& v : es[p]) {if (chmin(d[v.first], -big)) {q.push(v.first);}}}}}vl getpath(mat& es, vl& d, ll s, ll g) {vl res;ll x = s;while (x != g){res.push_back(x);for (auto v : es[x]) {if (d[v] == d[x] - 1) {x = v;break;}}}res.push_back(x);reverse(all(res));return res;}/// <summary>/// ベルマンフォード/// </summary>/// <param name="es"></param>/// <param name="d"></param>/// <param name="s"></param>void belman(vector<vpll>& es, vl& d, ll s) {d.resize(n + 1, big);d[s] = 0;rep(i, n + 1) {bool e = false;rep2(f, 1, n + 1) {if (d[f] == big)continue;for (auto& v : es[f]) {if (chmin(d[v.first], d[f] + v.second)) {e = true;}}}if (!e)return;}queue<ll> q;rep2(f, 1, n + 1) {if (d[f] == big)continue;for (auto& v : es[f]) {if (chmin(d[v.first], d[f] + v.second)) {q.push(v.first);}}}while (!q.empty()){auto p = frontpop(q);for (auto& v : es[p]) {if (d[v.first] > -big) {d[v.first] = -big;q.push(v.first);}}}}template<class t>void put_line(vector<t>& p) {rep(i, p.size()) {cout << p[i] << " ";}cout << endl;}mat tablecut(ll h, ll w, vector<string> t) {ll top = 0;rep(i, h) {bool ok = true;rep(j, w) {if (t[i][j] == '#') {ok = false;break;}}if (!ok)break;top++;}ll bot = h;for (int i = h - 1; i >= 0; i--){bool ok = true;rep(j, w) {if (t[i][j] == '#') {ok = false;break;}}if (!ok)break;bot--;}ll lf = 0;rep(i, w) {bool ok = true;rep(j, h) {if (t[j][i] == '#') {ok = false;break;}}if (!ok)break;lf++;;}ll ri = w;for (int i = w - 1; i >= 0; i--){bool ok = true;rep(j, h) {if (t[j][i] == '#') {ok = false;break;}}if (!ok)break;ri--;}mat tb(bot - top, vl(ri - lf));rep2(i, top, bot) {rep2(j, lf, ri) {if (t[i][j] == '#') {tb[i - top][j - lf] = 1;}}}return tb;}mat tablerotate(ll h, ll w, mat& a) {mat b(w, vl(h));rep(i, h) {rep(j, w) {b[w - j - 1][i] = a[i][j];}}return b;}ll rangeadd_op(ll l, ll r) {return max(l, r);}ll rangeadd_e() {return -big;}ll range_add_map(ll l, ll r) {if (l == -big)return r;if (r == -big)return l;return l + r;}ll range_add_comp(ll l, ll r) {return l + r;}ll rangeadd_id() {return 0;}lazy_segtree<ll, rangeadd_op, rangeadd_e, ll, range_add_map, range_add_comp, rangeadd_id>create_range_add_st(ll n) {return lazy_segtree<ll,rangeadd_op,rangeadd_e,ll,range_add_map,range_add_comp,rangeadd_id>(n + 1);}class rolhash_lib {string s;vl v, p;ll n;public:rolhash_lib(string _s) : s(_s) {n = s.size();v.resize(n + 1);p.resize(n + 1);p[0] = 1;rep(i, n) {v[i + 1] = calc_mod_61(mul_61(v[i], INF) + s[i]);p[i + 1] = mul_61(p[i], INF);}}ll get_hash(ll l, ll r) {l--;return calc_mod_61(v[r] + MOD * 4 - mul_61(v[l], p[r - l]));}};long long llceil(long long a, long long b) {if (a % b == 0) { return a / b; }if (a >= 0) { return (a / b) + 1; }else { return -((-a) / b); }}long long llfloor(long long a, long long b) {if (a % b == 0) { return a / b; }if (a >= 0) { return (a / b); }else { return -((-a) / b) - 1; }}using pl = pair<long long, long long>;pl findseg(pl seg, long long ini, long long step) {if (step > 0) {return { llceil(seg.first - ini,step), llfloor(seg.second - ini,step) };}else {step *= -1;return { llceil(ini - seg.second,step), llfloor(ini - seg.first,step) };}}ll __parity(ll t) {ll c = 0;while (t > 0){c += t & 1;t >>= 1;}return c % 2;}ll lcm(ll a, ll b) {return a * b / gcd(a, b);}struct centroid_decomposition {int n;int centor;mat G;vector<int>size;vector<vector<array<ll, 3>>>child; //child[i]=iが重心の木の、iを根としたときの子の(index,size,centoroid index)vector<bool>removed; //作業用centroid_decomposition(mat& g) {G = g;n = G.size();size.resize(n);child.resize(n);removed.resize(n);decompose();};int find_centroid(int v, int pre, int cnt) {// 残っている頂点でなす、vを含む連結成分における重心のindexを返す// early returnはせず、sizeの再計算を全部やるsize[v] = 1;bool ok = true;int centor = -1;for (auto vv : G[v]) {if (vv == pre)continue;if (removed[vv])continue;centor = max(centor, find_centroid(vv, v, cnt));size[v] += size[vv];ok &= size[vv] <= cnt / 2;}ok &= cnt - size[v] <= cnt / 2;return ok ? v : centor;}int decompose_recursive(int v, int cnt) {int vv = find_centroid(v, -1, cnt);removed[vv] = true;for (auto vvv : G[vv])if (!removed[vvv]) {int ccc = size[vvv] < size[vv] ? size[vvv] : cnt - size[vv];child[vv].push_back({ vvv,ccc,-1 });}for (auto& item : child[vv])item[2] = decompose_recursive(item[0], item[1]);return vv;}void decompose() {centor = decompose_recursive(0, n);}};template <typename T>vl argsort(const vector<T>& A) {// stablevl ids(A.size());iota(all(ids), 0);sort(all(ids),[&](int i, int j) { return A[i] < A[j] || (A[i] == A[j] && i < j); });return ids;}// A[I[0]], A[I[1]], ...template <typename T>vector<T> rearrange(const vector<T>& A, const vl& I) {int n = A.size();vector<T> B(n);rep(i, n) B[i] = A[I[i]];return B;}// ここまでライブラリ// ここからコードstruct C {ll a, mi;};struct O {ll l, r, q;};struct S {ll sz, val;};S op(S l, S r) {return { l.sz + r.sz,l.val + r.val };}S e() {return { 0,0 };}S mapping(ll f, S s) {if (f == -1)return s;return { s.sz,f * s.sz };}ll composition(ll ne, ll ol) {if (ne < 0)return ol;if (ol < 0)return ne;return ne;}ll id() {return -1;}ll opmin(ll l, ll r) {return min(l, r);}ll emin() {return big;}ll opma(ll l, ll r) {return max(l, r);}ll emi() {return -big;}ll oppp(ll l, ll r) {return max(l, r);}ll eee() {return -big;}modint998244353 o1(modint998244353 l, modint998244353 r) {return l + r;}modint998244353 e1() {return 0;}struct F {ll lz = 0, lo = 0, rz = 0, ro = 0, mz = 0, mo = 0, len = 0;};F ost(F l, F r) {if (l.len == -1)return r;if (r.len == -1)return l;ll lz = l.lz;ll lo = l.lo;ll rz = r.rz;ll ro = r.ro;if (rz == r.len) {rz += l.rz;}if (ro == r.len) {ro += l.ro;}if (lz == l.len) {lz += r.lz;}if (lo == l.len) {lo += r.lo;}ll sm = l.len + r.len;ll mo = max({ l.mo ,r.mo,l.ro + r.lo });ll mz = max({ l.mz,r.mz, l.rz + r.lz });return { lz,lo,rz,ro,mz,mo,sm };}F est() {return { -1,-1,-1,-1,-1,-1,-1 };}F maest(ll v, F s) {if (v % 2 == 0)return s;return { s.lo,s.lz,s.ro,s.rz,s.mo,s.mz,s.len };}vl o157(vl l, vl r) {if (l.empty())return r;if (r.empty())return l;rep(i, 26) {r[i] += l[i];}return r;}vl e157() {return {};}void solv() {/*私は素因数分解を使うべきところで、エラトステネスを使ってハマりました。私は「lからrまでを数としてみた時、7で割り切れるか?」を「lからrまでを数としてみた時、『各桁の和を』7で割り切れるか?」と誤解しました。私は累積和を使うべきところで、遅延セグ木を使ってTLEを食らいました。tをn進法にする時は素直にwhile(t>0)の条件で処理しよう問題を誤読すると痛いよ!愚直解テストはレンジの小さい範囲も入念に試しておきたい(https://atcoder.jp/contests/abc309/tasks/abc309_f)next_permutation使う時は基本的にはソートするんやm回接続(ループ)してその中を計算するタイプの問題、確定している分はしっかりmから引く事ARCでは特に、愚直解との比較で間違っている箇所は出来る限り出す*/cin >> k >> m >> n;mat a(k * k, vl(k * k));vl s(k * k);rep(i, m) {ll p, q, r;cin >> p >> q >> r;p--; q--; r--;a[p * k + q][q * k + r]++;if (p == 0) {s[q * k + r]++;}}a = pow(a, n - 3);s = mulMatVec(a, s);modint1000000007 res = 0;rep(i, k) {res += s[i * k];}plm(res);}int main(){cin.tie(0);ios::sync_with_stdio(false);//INF = 998244353;solv();return 0;}