#include #pragma GCC optimize("O3") #pragma GCC optimize("unroll-loops") templatebool chmin(S&a,T b){if(a>b){a=b;return true;}return false;} templatebool chmax(S&a,T b){if(aT Min(T a,T b){return aT Min(T a,T b,Args...args){return Min(Min(a,b),args...);} templateT Max(T a,T b){return a>b?a:b;} templateT Max(T a,T b,Args...args){return Max(Max(a,b),args...);} #define rep(i,n) for (ll i = 0;i < (ll)(n);i++) #define Yes cout << "Yes\n"// YESの短縮 #define No cout << "No\n"// NOの短縮 #define YN(x) cout<<((x)?"Yes":"No")<<'\n' #define rtr0 return(0)//return(0)の短縮 #define gyakugen(x) modpow(x,mod - 2,mod) #define agyakugen(x) modpow(x,amod - 2,amod) #define st(A) sort((A).begin(),(A).end()) #define rst(A) sort((A).rbegin(),(A).rend()) #define rev(A) reverse((A).begin(),(A).end()) #define unq(A) (A).erase(unique((A).begin(),(A).end()),(A).end()) #define all(A) (A).begin(),(A).end() #define rall(A) (A).rbegin(),(A).rend() using namespace std; using ll = long long;//63bit型整数型 using ld = long double;//doubleよりも長い値を保存できるもの using ull = unsigned long long;//符号がない64bit型整数 template using maxpq = priority_queue; template using minpq = priority_queue,greater>; ll mod = 998244353; ll amod = 1000000007; ll MINF = -5000000000000000000LL; ll INF = 50000000000000LL; ll inf = 2000000000; ll minf = -2000000000; ll BAD = -1; ll zero = 0; ld EPS = 1e-10; vectorrandomhash = {(ll)1e9 + 7,(ll)1e9 + 801,((ll)1e8 * 8) + 29,((ll)1e8 * 7) + 159,((ll)1e8 * 9) + 221}; vectortate = {0,-1,0,1};//グリッド上の全探索時の四方向の上下のチェック vectoryoko = {1,0,-1,0};//グリッド上の全探索時の四方向の右左のチェック vectoretate = {0,-1,-1,-1,0,1,1,1};//グリッド上の全探索時の八方向の上下のチェック vectoreyoko = {1,1,0,-1,-1,-1,0,1};//グリッド上の全探索時の八方向の右左のチェック vectorhexsax = {0,1,1,0,-1,-1}; vectorhexsay = {1,1,0,-1,-1,0}; // 素数 vector isprime; vector Era(int n){// [0,n) の素数一覧 isprime.assign(max(0,n),true); vector res; if(n<=0)return res; isprime[0]=false; if(n==1)return res; isprime[1]=false; for(ll i=2;i0); } // 数学 ull modmul(ull a,ull b,ull md){ return (ull)((__uint128_t)a*b%md); } ll modpow(ll a,ll n,ll md){ assert(md>0&&n>=0); a%=md;if(a<0)a+=md; ll res=1%md; while(n>0){ if(n&1)res=(ll)((__int128)res*a%md); a=(ll)((__int128)a*a%md); n>>=1; } return res; } long long npow(long long a, long long n){ long long res = 1; while (n > 0) { if (n & 1) res = res * a; a = a * a; n >>= 1; } return res; } long long isqrt(long long num){ assert(num>=0); ll x=(ll)sqrtl((ld)num); while((x+1)>0&&(x+1)<=num/(x+1))x++; while(x>0&&x>num/x)x--; return x; } ld get_theta(ld px,ld py,ld fx,ld fy,ld sx,ld sy){ ld fxv=fx-px,fyv=fy-py,sxv=sx-px,syv=sy-py; ld pfs=hypotl(fxv,fyv),pss=hypotl(sxv,syv); assert(pfs>0&&pss>0); ld c=(fxv*sxv+fyv*syv)/(pfs*pss); c=max((ld)-1,min((ld)1,c)); return acosl(c)*180.0L/acosl(-1.0L); } ld Euclidean_distance(ll x1,ll y1,ll x2,ll y2){ return hypotl((ld)x1-x2,(ld)y1-y2); } ll Manhattan_distance(ll x1,ll y1,ll x2,ll y2){ return abs(x1-x2)+abs(y1-y2); }; void change_bit(ll N,ll end,vector&X){ if((ll)X.size()>i)&1ULL):0); } ll popcount(ll x){return __builtin_popcountll((ull)x);} ll cutup(ll a,ll b){return ceil_div(a,b);} void Run_Length_Encoding(const string&A,vector>&RLE){ RLE.clear(); if(A.empty())return; RLE.push_back({A[0],1}); for(ll i=1;i<(ll)A.size();i++){ if(RLE.back().first==A[i])RLE.back().second++; else RLE.push_back({A[i],1}); } } bool is_in_grid(ll i,ll j,ll H,ll W){return 0<=i&&i vals; vector B=coordinate_compress(A,vals); template vector coordinate_compress(const vector&A,vector&vals){ vals=A;sort(vals.begin(),vals.end());vals.erase(unique(vals.begin(),vals.end()),vals.end()); vector res(A.size()); for(int i=0;i<(int)A.size();i++)res[i]=(int)(lower_bound(vals.begin(),vals.end(),A[i])-vals.begin()); return res; } // 素因数分解 O(sqrt(N)) vector> prime_factorize(ll n){ assert(n>=1);vector> res; for(ll p=2;p<=n/p;p+=(p==2?1:2))if(n%p==0){ int cnt=0;while(n%p==0)n/=p,cnt++; res.push_back({p,cnt}); } if(n>1)res.push_back({n,1}); return res; } // 約数列挙 O(sqrt(N))、昇順 vector divisors(ll n){ assert(n>=1);vector a,b; for(ll i=1;i<=n/i;i++)if(n%i==0){a.push_back(i);if(i!=n/i)b.push_back(n/i);} reverse(b.begin(),b.end());a.insert(a.end(),b.begin(),b.end());return a; } template class ModInt { private: long long val; // 拡張ユークリッドの互除法で逆元を計算 static long long mod_pow(long long base,long long exp,long long md) { long long result = 1; base%=md; while(exp>0){ if(exp&1)result=(long long)((__int128)result*base%md); base=(long long)((__int128)base*base%md); exp >>= 1; } return result; } // フェルマーの小定理を使った逆元計算(MODが素数の場合) static long long mod_inv(long long a,long long md) { return mod_pow(a,md-2,md); } public: // コンストラクタ ModInt() : val(0) {} ModInt(long long x) : val(((x % MOD) + MOD) % MOD) {} // 値の取得 long long value() const { return val; } // 四則演算の演算子オーバーロード ModInt operator+(const ModInt& other) const { return ModInt((val + other.val) % MOD); } ModInt operator-(const ModInt& other) const { return ModInt((val - other.val + MOD) % MOD); } ModInt operator*(const ModInt& other) const { return ModInt((long long)((__int128)val*other.val%MOD)); } ModInt operator/(const ModInt& other) const { assert(other.val != 0); // 0除算チェック return ModInt((long long)((__int128)val*mod_inv(other.val,MOD)%MOD)); } // 代入演算子 ModInt& operator+=(const ModInt& other) { val = (val + other.val) % MOD; return *this; } ModInt& operator-=(const ModInt& other) { val = (val - other.val + MOD) % MOD; return *this; } ModInt& operator*=(const ModInt& other) { val=(long long)((__int128)val*other.val%MOD); return *this; } ModInt& operator/=(const ModInt& other) { assert(other.val != 0); // 0除算チェック val=(long long)((__int128)val*mod_inv(other.val,MOD)%MOD); return *this; } // 比較演算子 bool operator==(const ModInt& other) const { return val == other.val; } bool operator!=(const ModInt& other) const { return val != other.val; } // 単項演算子 ModInt operator+() const { return *this; } ModInt operator-() const { return ModInt(val == 0 ? 0 : MOD - val); } // べき乗 ModInt pow(long long exp) const { return ModInt(mod_pow(val, exp, MOD)); } ModInt inv() const { assert(val!=0); return ModInt(mod_inv(val,MOD)); } // 出力用 friend std::ostream& operator<<(std::ostream& os, const ModInt& m) { return os << m.val; } // 入力用 friend std::istream& operator>>(std::istream& is, ModInt& m) { long long x; is >> x; m = ModInt(x); return is; } }; // Rolling Hash template struct rolling_hash{ vectorPower,hash,InvPower; ll B = 0; ll MOD = 0; void set_number(ll base,ll md){ assert(md>1); B=base%md;if(B<0)B+=md; MOD=md; assert(B!=0); } void do_hash(const T &S) { assert(MOD>1&&B!=0); ll N = S.size(); Power.resize(N+1); InvPower.resize(N+1); hash.resize(N+1); Power[0] = 1; InvPower[0] = 1; ull invB=modpow(B,MOD-2,MOD); for(ll i=0;i struct Floyd_Warshall{ vector> ans; int N=0; static constexpr T INF_T=numeric_limits::max()/4; void reset(int n){ N=n; ans.assign(N,vector(N,INF_T)); for(int i=0;i struct combination{ vector factorial,invfactorial; ll MOD,N; void reset(T n,T md){N=(ll)n+1;MOD=md;factorial.assign(N,1);invfactorial.assign(N,1);} void calu(){ assert(1=1;i--)invfactorial[i-1]=(T)((__int128)invfactorial[i]*i%MOD); } T get(T n,T r)const{ if(r<0||r>n||n<0||n>=N)return 0; return (T)((__int128)factorial[n]*invfactorial[r]%MOD*invfactorial[n-r]%MOD); } T permutation(T n,T r)const{ if(r<0||r>n||n<0||n>=N)return 0; return (T)((__int128)factorial[n]*invfactorial[n-r]%MOD); } }; // Dijkstra template struct dijkstra{ vector>> graph; vector ans;vector prev; priority_queue,vector>,greater>> pq; static constexpr T INF_T=numeric_limits::max()/4; void do_dijkstra(int start){ ans.assign(graph.size(),INF_T);prev.assign(graph.size(),-1);pq={}; pq.push({0,start});ans[start]=0; while(!pq.empty()){ auto [cost,vertex]=pq.top();pq.pop(); if(cost!=ans[vertex])continue; for(auto [nextvertex,w]:graph[vertex]){ T nextcost=cost+w; if(!chmin(ans[nextvertex],nextcost))continue; prev[nextvertex]=vertex;pq.push({nextcost,nextvertex}); } } } void make_indirectedgraph(int u,int v,T cost){graph[u].push_back({v,cost});graph[v].push_back({u,cost});} void make_directedgraph(int u,int v,T cost){graph[u].push_back({v,cost});} T output(int end){return ans[end];} vector path(int end)const{ if(end<0||end>=(int)ans.size()||ans[end]==INF_T)return {}; vector res;for(int v=end;v!=-1;v=prev[v])res.push_back(v); reverse(res.begin(),res.end());return res; } void reset(int N){graph.assign(N,{});ans.assign(N,INF_T);prev.assign(N,-1);pq={};} }; // BFS(重みなし) vector bfs(const vector>&graph,int start){ int N=(int)graph.size();vector dist(N,-1);queue q; dist[start]=0;q.push(start); while(!q.empty()){ int v=q.front();q.pop(); for(int to:graph[v])if(dist[to]==-1)dist[to]=dist[v]+1,q.push(to); } return dist; } vector bfs(const vector>&graph,const vector&starts){ int N=(int)graph.size();vector dist(N,-1);queue q; for(int s:starts)if(dist[s]==-1)dist[s]=0,q.push(s); while(!q.empty()){ int v=q.front();q.pop(); for(int to:graph[v])if(dist[to]==-1)dist[to]=dist[v]+1,q.push(to); } return dist; } // 01-BFS: 辺の重みは0か1 vector bfs01(const vector>>&graph,int start){ int N=(int)graph.size(),I=numeric_limits::max()/4;vector dist(N,I);deque q; dist[start]=0;q.push_front(start); while(!q.empty()){ int v=q.front();q.pop_front(); for(auto [to,w]:graph[v]){ assert(w==0||w==1); if(dist[to]<=dist[v]+w)continue; dist[to]=dist[v]+w; if(w)q.push_back(to);else q.push_front(to); } } return dist; } // トポロジカルソート。閉路があると空vectorを返す vector topological_sort(const vector>&graph){ int N=(int)graph.size();vector indeg(N),res;queue q; for(int v=0;v struct unionfind { public: vector parent, rank; void reset(T N) { // 初期化 parent.resize(N); rank.assign(N, 1); // 各集合のサイズを 1 にする for (T i = 0; i < N; i++) parent[i] = i; } T leader(T x) { // 経路圧縮による親の取得 if (parent[x] == x) return x; return parent[x] = leader(parent[x]); // 経路圧縮 } void marge(T x,T y){ // 既存名を維持 T a=leader(x),b=leader(y); if(a==b)return; if(rank[a]> groups(){ vector> res(parent.size()); for(T i=0;i<(T)parent.size();i++)res[leader(i)].push_back(i); res.erase(remove_if(res.begin(),res.end(),[](const vector&v){return v.empty();}),res.end()); return res; } void check(T N) { // デバッグ用: 親の確認 for (T i = 0; i < N; i++) cout << parent[i] << " "; cout << "\n"; } }; // SCC struct SCC { //kosaraju法を用いたSCC int N; // グラフ vector> g, rg; // Kosaraju 用 vector comp, order; vector used; // 結果 int scc_count; vector> groups; // 各 SCC に含まれる頂点 vector> dag; // 縮約 DAG vector sz; // SCC サイズ vector indeg, outdeg; // DAG の入出力次数 // --- コンストラクタ --- SCC() : N(0) {} SCC(int n) { reset(n); } void reset(int n) { N = n; g.assign(N, {}); rg.assign(N, {}); } void add_edge(int u, int v) { g[u].push_back(v); rg[v].push_back(u); } // --- 1回目 DFS(帰りがけ順) --- //stackに積む行動 void dfs1(int v) { used[v] = true; for (int to : g[v]) { if (!used[to]) dfs1(to); } order.push_back(v); } // --- 2回目 DFS(逆グラフ) --- //stackに積んだものを集合に直す行動 void dfs2(int v, int c) { comp[v] = c; groups[c].push_back(v); for (int to : rg[v]) { if (comp[to] == -1) dfs2(to, c); } } void do_scc() { // 1st DFS used.assign(N, false); order.clear(); for (int i = 0; i < N; i++) { if (!used[i]) dfs1(i); } // 2nd DFS comp.assign(N, -1); scc_count = 0; groups.clear(); for (int i = N - 1; i >= 0; i--) { int v = order[i]; if (comp[v] == -1) { groups.push_back({}); dfs2(v, scc_count); scc_count++; } } // SCC サイズ sz.assign(scc_count, 0); for (int i = 0; i < scc_count; i++) { sz[i] = (int)groups[i].size(); } // 縮約 DAG 構築 dag.assign(scc_count, {}); indeg.assign(scc_count, 0); outdeg.assign(scc_count, 0); // 重複辺除去 set> seen; for (int v = 0; v < N; v++) { for (int to : g[v]) { int a = comp[v]; int b = comp[to]; if (a != b && !seen.count({a, b})) { seen.insert({a, b}); dag[a].push_back(b); outdeg[a]++; indeg[b]++; } } } } }; // Fenwick Tree: 0-indexed。add(p,x), sum(l,r)=[l,r) template struct FenwickTree{ int N=0;vector bit; FenwickTree()=default; explicit FenwickTree(int n){reset(n);} explicit FenwickTree(const vector&A){ reset((int)A.size()); for(int i=0;i0;r-=r&-r)res+=bit[r];return res;} T sum(int l,int r)const{assert(0<=l&&l<=r&&r<=N);return sum(r)-sum(l);} T get(int p)const{return sum(p,p+1);} // 累積和がx以上となる最小index。全要素が非負のとき使用 int lower_bound(T x)const{ if(x<=T{})return 0; int p=0;T s{};int k=1;while((k<<1)<=N)k<<=1; for(;k;k>>=1)if(p+k<=N&&s+bit[p+k] struct segtree { public: segtree() : segtree(0) {} segtree(int n) : segtree(std::vector(n, e())) {} segtree(const std::vector& v) : _n(int(v.size())){ log = ceil_pow2(_n); size = 1 << log; d = std::vector(2 * size, e()); for (int i = 0; i < _n; i++) d[size + i] = v[i]; for (int i = size - 1; i >= 1; i--) { update(i); } } void set(int p, S x) { assert(0 <= p && p < _n); p += size; d[p] = x; for (int i = 1; i <= log; i++) update(p >> i); } S get(int p) { assert(0 <= p && p < _n); return d[p + size]; } S prod(int l, int r) { assert(0 <= l && l <= r && r <= _n); S sml = e(), smr = e(); l += size; r += size; while (l < r) { if (l & 1) sml = op(sml, d[l++]); if (r & 1) smr = op(d[--r], smr); l >>= 1; r >>= 1; } return op(sml, smr); } S all_prod() { return d[1]; } template int max_right(int l) { return max_right(l, [](S x) { return f(x); }); } template int max_right(int l, F f) { assert(0 <= l && l <= _n); assert(f(e())); if (l == _n) return _n; l += size; S sm = e(); do{ while (l % 2 == 0) l >>= 1; if (!f(op(sm, d[l]))) { while (l < size) { l = (2 * l); if (f(op(sm, d[l]))) { sm = op(sm, d[l]); l++; } } return l - size; } sm = op(sm, d[l]); l++; }while ((l & -l) != l); return _n; } template int min_left(int r) { return min_left(r, [](S x) { return f(x); }); } template int min_left(int r, F f) { assert(0 <= r && r <= _n); assert(f(e())); if (r == 0) return 0; r += size; S sm = e(); do{ r--; while (r > 1 && (r % 2)) r >>= 1; if (!f(op(d[r], sm))) { while (r < size) { r = (2 * r + 1); if (f(op(d[r], sm))) { sm = op(d[r], sm); r--; } } return r + 1 - size; } sm = op(d[r], sm); }while ((r & -r) != r); return 0; } private: int _n, size, log; std::vector d; void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); } int ceil_pow2(int n) { int x = 0; while ((1U << x) < (unsigned int)(n)) x++; return x; } }; // Lazy Segment Tree template struct lazy_segtree { public: lazy_segtree() : lazy_segtree(0) {} lazy_segtree(int n) : lazy_segtree(std::vector(n, e())) {} lazy_segtree(const std::vector& v) : _n(int(v.size())) { log = ceil_pow2(_n); size = 1 << log; d = std::vector(2 * size, e()); lz = std::vector(size, id()); for (int i = 0; i < _n; i++) d[size + i] = v[i]; for (int i = size - 1; i >= 1; i--) { update(i); } } void set(int p, S x) { assert(0 <= p && p < _n); p += size; for (int i = log; i >= 1; i--) push(p >> i); d[p] = x; for (int i = 1; i <= log; i++) update(p >> i); } S get(int p) { assert(0 <= p && p < _n); p += size; for (int i = log; i >= 1; i--) push(p >> i); return d[p]; } S prod(int l, int r) { assert(0 <= l && l <= r && r <= _n); if (l == r) return e(); l += size; r += size; for (int i = log; i >= 1; i--) { if (((l >> i) << i) != l) push(l >> i); if (((r >> i) << i) != r) push(r >> i); } S sml = e(), smr = e(); while (l < r) { if (l & 1) sml = op(sml, d[l++]); if (r & 1) smr = op(d[--r], smr); l >>= 1; r >>= 1; } return op(sml, smr); } S all_prod() { return d[1]; } void apply(int p, F f) { assert(0 <= p && p < _n); p += size; for (int i = log; i >= 1; i--) push(p >> i); d[p] = mapping(f, d[p]); for (int i = 1; i <= log; i++) update(p >> i); } void apply(int l, int r, F f) { assert(0 <= l && l <= r && r <= _n); if (l == r) return; l += size; r += size; for (int i = log; i >= 1; i--) { if (((l >> i) << i) != l) push(l >> i); if (((r >> i) << i) != r) push((r - 1) >> i); } { int l2 = l, r2 = r; while (l < r) { if (l & 1) all_apply(l++, f); if (r & 1) all_apply(--r, f); l >>= 1; r >>= 1; } l = l2; r = r2; } for (int i = 1; i <= log; i++) { if (((l >> i) << i) != l) update(l >> i); if (((r >> i) << i) != r) update((r - 1) >> i); } } template int max_right(int l) { return max_right(l, [](S x) { return g(x); }); } template int max_right(int l, G g) { assert(0 <= l && l <= _n); assert(g(e())); if (l == _n) return _n; l += size; for (int i = log; i >= 1; i--) push(l >> i); S sm = e(); do { while (l % 2 == 0) l >>= 1; if (!g(op(sm, d[l]))) { while (l < size) { push(l); l = (2 * l); if (g(op(sm, d[l]))) { sm = op(sm, d[l]); l++; } } return l - size; } sm = op(sm, d[l]); l++; } while ((l & -l) != l); return _n; } template int min_left(int r) { return min_left(r, [](S x) { return g(x); }); } template int min_left(int r, G g) { assert(0 <= r && r <= _n); assert(g(e())); if (r == 0) return 0; r += size; for (int i = log; i >= 1; i--) push((r - 1) >> i); S sm = e(); do { r--; while (r > 1 && (r % 2)) r >>= 1; if (!g(op(d[r], sm))) { while (r < size) { push(r); r = (2 * r + 1); if (g(op(d[r], sm))) { sm = op(d[r], sm); r--; } } return r + 1 - size; } sm = op(d[r], sm); } while ((r & -r) != r); return 0; } private: int _n, size, log; std::vector d; std::vector lz; int ceil_pow2(int n) { int x = 0; while ((1U << x) < (unsigned int)(n)) x++; return x; } void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); } void all_apply(int k, F f) { d[k] = mapping(f, d[k]); if (k < size) lz[k] = composition(f, lz[k]); } void push(int k) { all_apply(2 * k, lz[k]); all_apply(2 * k + 1, lz[k]); lz[k] = id(); } }; // Grid template void rotate(vector>& ary,bool rev=false){ if(ary.empty()||ary[0].empty())return; int n=ary.size(),m=ary[0].size(); vector copy(m,vector(n)); rep(i,n)rep(j,m){ if(!rev)copy[j][n-i-1]=ary[i][j]; else copy[m-j-1][i]=ary[i][j]; } ary=copy; } // Segment Tree presets using segS = ll; segS oop(segS a,segS b){ return a+b; } segS ee(){ return 0; } struct segS2{ ll sum; ll mn; }; segS2 o3p(segS2 a,segS2 b){ segS2 res; res.sum=a.sum+b.sum; res.mn = min(a.mn,a.sum+b.mn); return res; } segS2 e3(){ return {0,0}; } //遅延セグ木のベース using mint = ModInt<998244353>; using amint = ModInt<1000000007>; void print_1D(const vector&A,bool kaigyou){ ll N = A.size(); cout << "----------\n"; for(int i = 0;i>&A){ ll N = A.size(); cout << "----------\n"; for(int i = 0;i prefix_1Dsum(const vector&A){ ll N = A.size(); vectorB(N+1); for(int i = 0;i> prefix_2Dsum(const vector>&A){ ll N = A.size(); ll M = A[0].size(); vector>B(N+1,vector(M+1)); for(int i = 0;i&A,ll l,ll r){// 1-indexed, [l,r] assert(1<=l&&l<=r&&r<(ll)A.size()); return A[r]-A[l-1]; } ll get_prefix_2Dsum(const vector>&A,ll x1,ll y1,ll x2,ll y2){// 1-indexed, inclusive assert(1<=x1&&x1<=x2&&x2<(ll)A.size()); assert(1<=y1&&y1<=y2&&y2<(ll)A[0].size()); return A[x2][y2]-A[x1-1][y2]-A[x2][y1-1]+A[x1-1][y1-1]; } // 実行時間計測(AHCなど) struct Timer{ chrono::steady_clock::time_point start_time; Timer(){reset();} void reset(){start_time=chrono::steady_clock::now();} double ms()const{return chrono::duration(chrono::steady_clock::now()-start_time).count();} double sec()const{return ms()/1000.0;} }; struct XorShift64 { uint64_t x; XorShift64(uint64_t seed=88172645463325252ULL){ x = seed ? seed : 88172645463325252ULL; } inline uint64_t next_u64(){ x ^= x << 13; x ^= x >> 7; x ^= x << 17; return x; } inline uint32_t next_u32(){ return (uint32_t)next_u64(); } inline uint64_t next_int(uint64_t m){assert(m>0);return next_u64()%m;} inline ll next_ll(ll l,ll r){assert(l>11)*(1.0/9007199254740992.0);} // [0,1), 53-bit templatevoid shuffle_vector(vector&A){for(int i=(int)A.size()-1;i>0;i--)swap(A[i],A[next_int(i+1)]);} }; // Euler Tour using S = long long; S Sum_e(){return 0;} S Sum_op(S a,S b){return a+b;} using U = pair; U Min_e(){return {1000000000,1000000000};} U Min_op(U a,U b){return min(a,b);} class EulerTour{ public: EulerTour() : n(0),turn(0){} explicit EulerTour(const int &_n){ n = _n; turn = 0; Graph.assign(n,{}); vw.assign(n,0); finish.assign(n,0); discover.assign(n,0); init_v_cost1.assign(2*n, 0); init_e_cost1.assign(2*n, 0); init_v_cost2.assign(2*n, 0); init_e_cost2.assign(2*n, 0); init_depth_visit.assign(2*n, Min_e()); v_cost1 = segtree(2*n); e_cost1 = segtree(2*n); v_cost2 = segtree(2*n); e_cost2 = segtree(2*n); depth_visit = segtree(2*n); } inline void addEdge(const int &u, const int &v, const long long &w){ Graph[u].emplace_back(pair(v,w)); Graph[v].emplace_back(pair(u,w)); } inline void addVCost(const int &i,const long long &w){vw[i] = w;} inline void changeECost(int u,int v,const long long &nw){ // ※ Graph自体の更新はしていない if(discover[u] > discover[v])swap(u,v); // 辺は2回しか通らない → O(logN)で更新可 e_cost1.set(discover[v],nw); e_cost2.set(discover[v],nw); e_cost2.set(finish[v],-nw); } inline S distV(const int &u,const int &v){int a=lca(u,v);return rootV(u)+rootV(v)-2*rootV(a)+vw[a];} inline S distE(const int &u,const int &v){int a=lca(u,v);return rootE(u)+rootE(v)-2*rootE(a);} inline S partV(const int &root){return v_cost1.prod(discover[root],finish[root]);} inline S partE(const int &root){return e_cost1.prod(discover[root]+1,finish[root]);} inline int lca(int u, int v){ if(u == v)return u; if(discover[u] > discover[v])swap(u,v); return depth_visit.prod(discover[u],finish[v]+1).second; } inline void build(){ assert(n>0); turn=0; fill(init_v_cost1.begin(),init_v_cost1.end(),0); fill(init_e_cost1.begin(),init_e_cost1.end(),0); fill(init_v_cost2.begin(),init_v_cost2.end(),0); fill(init_e_cost2.begin(),init_e_cost2.end(),0); fill(init_depth_visit.begin(),init_depth_visit.end(),Min_e()); dfs(0,-1,0,0); v_cost1 = segtree(init_v_cost1); e_cost1 = segtree(init_e_cost1); v_cost2 = segtree(init_v_cost2); e_cost2 = segtree(init_e_cost2); depth_visit = segtree(init_depth_visit); } int n, turn; vector>> Graph; segtree v_cost1, e_cost1, v_cost2, e_cost2; segtree depth_visit; vector vw; vector discover,finish; vector init_v_cost1, init_e_cost1, init_v_cost2, init_e_cost2; vector init_depth_visit; // 0 → v の頂点・辺cost inline long long rootV(const int &v){return v_cost2.prod(0,discover[v]+1);} inline long long rootE(const int &v){return e_cost2.prod(1,discover[v]+1);} void dfs(const int &now,const int &pre,const long long &w,const int &d){ // 行きがけ処理 discover[now] = turn; init_depth_visit[turn] = U(d,now); init_v_cost1[turn] = vw[now]; init_v_cost2[turn] = vw[now]; init_e_cost1[turn] = w; init_e_cost2[turn] = w; turn++; for(auto &&[next,nw]:Graph[now]){ if(next == pre)continue; dfs(next,now,nw,d+1); } // 帰りがけ処理 finish[now] = turn; if(pre != -1)init_depth_visit[turn] = U(d-1,pre); init_v_cost1[turn] = 0; init_e_cost1[turn] = 0; init_v_cost2[turn] = -vw[now]; init_e_cost2[turn] = -w; turn++; } }; vector divisor(long long n) { vector ret; for (long long i = 1; i * i <= n; i++) { if (n % i == 0) { ret.push_back(i); if (i * i != n) ret.push_back(n / i); } } sort(ret.begin(), ret.end()); // 昇順に並べる return ret; } int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); string S; cin >> S; if(S.size()==1&&(S[0]=='2')){ cout << "0" << "\n"; Yes; rtr0; } if((S[S.size()-1]-'0')%2==0){ cout << 0 << "\n"; } else{ cout << 1 << "\n"; } No; return 0; }