using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using static System.Math;
using System.Text;
using System.Threading;

namespace Program
{
    public static class CODEFORCES2
    {
        static public void Solve()
        {
            Mod._mod = 998244353;
            var w = NN;
            var h = NN;
            Console.WriteLine(Pow((Mod)2, w) * Pow((Mod)2, h));

        }

        static public void Main(string[] args) { if (args.Length == 0) { var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false }; Console.SetOut(sw); } var t = new Thread(Solve, 134217728); t.Start(); t.Join(); Console.Out.Flush(); }
        static Random rand = new Random();
        static class Console_
        {
            static Queue<string> param = new Queue<string>();
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public static string NextString() { if (param.Count == 0) foreach (var item in Console.ReadLine().Split(' ')) param.Enqueue(item); return param.Dequeue(); }
        }
        static long NN => long.Parse(Console_.NextString());
        static double ND => double.Parse(Console_.NextString());
        static string NS => Console_.NextString();
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static long[] NNList(long N) => Repeat(0, N).Select(_ => NN).ToArray();
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static double[] NDList(long N) => Repeat(0, N).Select(_ => ND).ToArray();
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static string[] NSList(long N) => Repeat(0, N).Select(_ => NS).ToArray();
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static IEnumerable<T> OrderByRand<T>(this IEnumerable<T> x) => x.OrderBy(_ => rand.Next());
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static IEnumerable<T> Repeat<T>(T v, long n) => Enumerable.Repeat<T>(v, (int)n);
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static IEnumerable<int> Range(long s, long c) => Enumerable.Range((int)s, (int)c);
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static void RevSort<T>(T[] l) where T : IComparable { Array.Sort(l, (x, y) => y.CompareTo(x)); }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static void RevSort<T>(T[] l, Comparison<T> comp) where T : IComparable { Array.Sort(l, (x, y) => comp(y, x)); }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static IEnumerable<long> Primes(long x) { if (x < 2) yield break; yield return 2; var halfx = x / 2; var table = new bool[halfx + 1]; var max = (long)(Math.Sqrt(x) / 2); for (long i = 1; i <= max; ++i) { if (table[i]) continue; var add = 2 * i + 1; yield return add; for (long j = 2 * i * (i + 1); j <= halfx; j += add) table[j] = true; } for (long i = max + 1; i <= halfx; ++i) if (!table[i] && 2 * i + 1 <= x) yield return 2 * i + 1; }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static IEnumerable<long> Factors(long x) { if (x < 2) yield break; while (x % 2 == 0) { x /= 2; yield return 2; } var max = (long)Math.Sqrt(x); for (long i = 3; i <= max; i += 2) while (x % i == 0) { x /= i; yield return i; } if (x != 1) yield return x; }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static IEnumerable<long> Divisor(long x) { if (x < 1) yield break; var max = (long)Math.Sqrt(x); for (long i = 1; i <= max; ++i) { if (x % i != 0) continue; yield return i; if (i != x / i) yield return x / i; } }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static long GCD(long a, long b) { while (b > 0) { var tmp = b; b = a % b; a = tmp; } return a; }
        static long LCM(long a, long b) => a * b / GCD(a, b);
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static Mat<T> Pow<T>(Mat<T> x, long y) => Mat<T>.Pow(x, y);
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static T Pow<T>(T x, long y) { T a = (dynamic)1; while (y != 0) { if ((y & 1) == 1) a *= (dynamic)x; x *= (dynamic)x; y >>= 1; } return a; }
        static List<long> _fact = new List<long>() { 1 };
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static void _B(long n) { if (n >= _fact.Count) for (int i = _fact.Count; i <= n; ++i) _fact.Add(_fact[i - 1] * i); }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static long Comb(long n, long k) { _B(n); if (n == 0 && k == 0) return 1; if (n < k || n < 0) return 0; return _fact[(int)n] / _fact[(int)(n - k)] / _fact[(int)k]; }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static long Perm(long n, long k) { _B(n); if (n == 0 && k == 0) return 1; if (n < k || n < 0) return 0; return _fact[(int)n] / _fact[(int)(n - k)]; }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static Func<TR> Lambda<TR>(Func<Func<TR>, TR> f) { Func<TR> t = () => default(TR); return t = () => f(t); }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static Func<T1, TR> Lambda<T1, TR>(Func<T1, Func<T1, TR>, TR> f) { Func<T1, TR> t = x1 => default(TR); return t = x1 => f(x1, t); }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static Func<T1, T2, TR> Lambda<T1, T2, TR>(Func<T1, T2, Func<T1, T2, TR>, TR> f) { Func<T1, T2, TR> t = (x1, x2) => default(TR); return t = (x1, x2) => f(x1, x2, t); }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static Func<T1, T2, T3, TR> Lambda<T1, T2, T3, TR>(Func<T1, T2, T3, Func<T1, T2, T3, TR>, TR> f) { Func<T1, T2, T3, TR> t = (x1, x2, x3) => default(TR); return t = (x1, x2, x3) => f(x1, x2, x3, t); }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static Func<T1, T2, T3, T4, TR> Lambda<T1, T2, T3, T4, TR>(Func<T1, T2, T3, T4, Func<T1, T2, T3, T4, TR>, TR> f) { Func<T1, T2, T3, T4, TR> t = (x1, x2, x3, x4) => default(TR); return t = (x1, x2, x3, x4) => f(x1, x2, x3, x4, t); }
        class PQ<T> where T : IComparable
        {
            List<T> h; Comparison<T> c; public T Peek => h[0]; public int Count => h.Count;
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public PQ(int cap, Comparison<T> c, bool asc = true) { h = new List<T>(cap); this.c = asc ? c : (x, y) => c(y, x); }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public PQ(Comparison<T> c, bool asc = true) { h = new List<T>(); this.c = asc ? c : (x, y) => c(y, x); }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public PQ(int cap, bool asc = true) : this(cap, (x, y) => x.CompareTo(y), asc) { }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public PQ(bool asc = true) : this((x, y) => x.CompareTo(y), asc) { }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public void Push(T v) { var i = h.Count; h.Add(v); while (i > 0) { var ni = (i - 1) / 2; if (c(v, h[ni]) >= 0) break; h[i] = h[ni]; i = ni; } h[i] = v; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public T Pop() { var r = h[0]; var v = h[h.Count - 1]; h.RemoveAt(h.Count - 1); if (h.Count == 0) return r; var i = 0; while (i * 2 + 1 < h.Count) { var i1 = i * 2 + 1; var i2 = i * 2 + 2; if (i2 < h.Count && c(h[i1], h[i2]) > 0) i1 = i2; if (c(v, h[i1]) <= 0) break; h[i] = h[i1]; i = i1; } h[i] = v; return r; }
        }
        class PQ<TK, TV> where TK : IComparable
        {
            PQ<Tuple<TK, TV>> q; public Tuple<TK, TV> Peek => q.Peek; public int Count => q.Count;
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public PQ(int cap, Comparison<TK> c, bool asc = true) { q = new PQ<Tuple<TK, TV>>(cap, (x, y) => c(x.Item1, y.Item1), asc); }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public PQ(Comparison<TK> c, bool asc = true) { q = new PQ<Tuple<TK, TV>>((x, y) => c(x.Item1, y.Item1), asc); }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public PQ(int cap, bool asc = true) : this(cap, (x, y) => x.CompareTo(y), asc) { }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public PQ(bool asc = true) : this((x, y) => x.CompareTo(y), asc) { }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public void Push(TK k, TV v) => q.Push(Tuple.Create(k, v));
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public Tuple<TK, TV> Pop() => q.Pop();
        }
        public class UF
        {
            long[] d;
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public UF(long s) { d = Repeat(-1L, s).ToArray(); }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public bool Unite(long x, long y) { x = Root(x); y = Root(y); if (x != y) { if (d[y] < d[x]) { var t = y; y = x; x = t; } d[x] += d[y]; d[y] = x; } return x != y; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public bool IsSame(long x, long y) => Root(x) == Root(y);
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public long Root(long x) => d[x] < 0 ? x : d[x] = Root(d[x]);
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public long Count(long x) => -d[Root(d[x])];
        }
        struct Mod : IEquatable<object>
        {
            static public long _mod = 1000000007; long _val;
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public Mod(long x) { if (x < _mod && x >= 0) _val = x; else if ((_val = x % _mod) < 0) _val += _mod; }
            static public implicit operator Mod(long x) => new Mod(x);
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public implicit operator long(Mod x) => x._val;
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public Mod operator +(Mod x, Mod y) { var t = x._val + y._val; return t >= _mod ? new Mod { _val = t - _mod } : new Mod { _val = t }; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public Mod operator -(Mod x, Mod y) { var t = x._val - y._val; return t < 0 ? new Mod { _val = t + _mod } : new Mod { _val = t }; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public Mod operator *(Mod x, Mod y) => x._val * y._val;
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public Mod operator /(Mod x, Mod y) => x._val * Inverse(y._val);
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public bool operator ==(Mod x, Mod y) => x._val == y._val;
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public bool operator !=(Mod x, Mod y) => x._val != y._val;
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public long Inverse(long x) { long b = _mod, r = 1, u = 0, t = 0; while (b > 0) { var q = x / b; t = u; u = r - q * u; r = t; t = b; b = x - q * b; x = t; } return r < 0 ? r + _mod : r; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            bool IEquatable<object>.Equals(object obj) => obj == null ? false : Equals((Mod)obj);
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public override bool Equals(object obj) => obj == null ? false : Equals((Mod)obj);
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public bool Equals(Mod obj) => obj == null ? false : _val == obj._val;
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public override int GetHashCode() => _val.GetHashCode();
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public override string ToString() => _val.ToString();
            static List<Mod> _fact = new List<Mod>() { 1 };
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static void B(long n) { if (n >= _fact.Count) for (int i = _fact.Count; i <= n; ++i) _fact.Add(_fact[i - 1] * i); }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public Mod Comb(long n, long k) { B(n); if (n == 0 && k == 0) return 1; if (n < k || n < 0) return 0; return _fact[(int)n] / _fact[(int)(n - k)] / _fact[(int)k]; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public Mod Perm(long n, long k) { B(n); if (n == 0 && k == 0) return 1; if (n < k || n < 0) return 0; return _fact[(int)n] / _fact[(int)(n - k)]; }
        }
        struct Mat<T>
        {
            T[,] m;
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public Mat(T[,] v) { m = (T[,])v.Clone(); }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public implicit operator Mat<T>(T[,] v) => new Mat<T>(v);
            public T this[int r, int c] { get { return m[r, c]; } set { m[r, c] = value; } }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public Mat<T> operator +(Mat<T> a, T x) { var tm = (T[,])a.m.Clone(); for (int r = 0; r < tm.GetLength(0); ++r) for (int c = 0; c < tm.GetLength(1); ++c) tm[r, c] += (dynamic)x; return tm; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public Mat<T> operator +(Mat<T> a, Mat<T> b) { var tm = (T[,])a.m.Clone(); for (int r = 0; r < tm.GetLength(0); ++r) for (int c = 0; c < tm.GetLength(1); ++c) tm[r, c] += (dynamic)b[r, c]; return tm; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public Mat<T> operator -(Mat<T> a, T x) { var tm = (T[,])a.m.Clone(); for (int r = 0; r < tm.GetLength(0); ++r) for (int c = 0; c < tm.GetLength(1); ++c) tm[r, c] -= (dynamic)x; return tm; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public Mat<T> operator -(Mat<T> a, Mat<T> b) { var tm = (T[,])a.m.Clone(); for (int r = 0; r < tm.GetLength(0); ++r) for (int c = 0; c < tm.GetLength(1); ++c) tm[r, c] -= (dynamic)b[r, c]; return tm; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public Mat<T> operator *(Mat<T> a, T x) { var tm = (T[,])a.m.Clone(); for (int r = 0; r < tm.GetLength(0); ++r) for (int c = 0; c < tm.GetLength(1); ++c) tm[r, c] *= (dynamic)x; return tm; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public Mat<T> operator *(Mat<T> a, Mat<T> b) { var nr = a.m.GetLength(0); var nc = b.m.GetLength(1); var tm = new T[nr, nc]; for (int i = 0; i < nr; ++i) for (int j = 0; j < nc; ++j) tm[i, j] = (dynamic)0; for (int r = 0; r < nr; ++r) for (int c = 0; c < nc; ++c) for (int i = 0; i < a.m.GetLength(1); ++i) tm[r, c] += a[r, i] * (dynamic)b[i, c]; return tm; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public Mat<T> Pow(Mat<T> x, long y) { var n = x.m.GetLength(0); var t = (Mat<T>)new T[n, n]; for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j) t[i, j] = (dynamic)(i == j ? 1 : 0); while (y != 0) { if ((y & 1) == 1) t *= x; x *= x; y >>= 1; } return t; }
        }
        class Tree
        {
            long N; int l; List<long>[] p; int[] d; long[][] pr; long r; Tuple<long, long, int>[] e; Tuple<long, long>[] b; bool lca; bool euler; bool bfs;
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public Tree(List<long>[] p_, long r_) { N = p_.Length; p = p_; r = r_; lca = false; euler = false; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public Tuple<long, long>[] BFSRoot() { if (!bfs) { var nb = new List<Tuple<long, long>>(); var q = new Queue<long>(); var d = new bool[N]; nb.Add(Tuple.Create(r, -1L)); d[r] = true; q.Enqueue(r); while (q.Count > 0) { var w = q.Dequeue(); foreach (var i in p[w]) { if (d[i]) continue; d[i] = true; q.Enqueue(i); nb.Add(Tuple.Create(i, w)); } } b = nb.ToArray(); bfs = true; } return b; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public Tuple<long, long>[] BFSLeaf() => BFSRoot().Reverse().ToArray();
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public Tuple<long, long, int>[] Euler() { if (!euler) { var ne = new List<Tuple<long, long, int>>(); var s = new Stack<Tuple<long, long>>(); var d = new bool[N]; d[r] = true; s.Push(Tuple.Create(r, -1L)); while (s.Count > 0) { var w = s.Peek(); var ad = true; foreach (var i in p[w.Item1]) { if (d[i]) continue; d[i] = true; ad = false; s.Push(Tuple.Create(i, w.Item1)); } if (!ad || p[w.Item1].Count == 1) ne.Add(Tuple.Create(w.Item1, w.Item2, 1)); if (ad) { s.Pop(); ne.Add(Tuple.Create(w.Item1, w.Item2, -1)); } } e = ne.ToArray(); euler = true; } return e; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public long LCA(long u, long v) { if (!lca) { l = 0; while (N > (1 << l)) l++; d = new int[N]; pr = Repeat(0, l).Select(_ => new long[N]).ToArray(); d[r] = 0; pr[0][r] = -1; var q = new Stack<long>(); q.Push(r); while (q.Count > 0) { var w = q.Pop(); foreach (var i in p[w]) { if (i == pr[0][w]) continue; q.Push(i); d[i] = d[w] + 1; pr[0][i] = w; } } for (var k = 0; k + 1 < l; k++) for (var w = 0; w < N; w++) if (pr[k][w] < 0) pr[k + 1][w] = -1; else pr[k + 1][w] = pr[k][pr[k][w]]; lca = true; } if (d[u] > d[v]) { var t = u; u = v; v = t; } for (var k = 0; k < l; k++) if ((((d[v] - d[u]) >> k) & 1) != 0) v = pr[k][v]; if (u == v) return u; for (var k = l - 1; k >= 0; k--) if (pr[k][u] != pr[k][v]) { u = pr[k][u]; v = pr[k][v]; } return pr[0][u]; }
        }
        class BT<T> where T : IComparable
        {
            class Node { public Node l; public Node r; public T v; public bool b; }
            Comparison<T> c; Node r; bool ch; T lm;
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public BT(Comparison<T> _c) { c = _c; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public BT() : this((x, y) => x.CompareTo(y)) { }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            bool R(Node n) => n != null && !n.b;
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            bool B(Node n) => n != null && n.b;
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            Node RtL(Node n) { Node m = n.r, t = m.l; m.l = n; n.r = t; return m; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            Node RtR(Node n) { Node m = n.l, t = m.r; m.r = n; n.l = t; return m; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            Node RtLR(Node n) { n.l = RtL(n.l); return RtR(n); }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            Node RtRL(Node n) { n.r = RtR(n.r); return RtL(n); }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public void Add(T x) { r = A(r, x); r.b = true; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            Node A(Node n, T x) { if (n == null) { ch = true; return new Node() { v = x }; } if (c(x, n.v) < 0) n.l = A(n.l, x); else n.r = A(n.r, x); return Bl(n); }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            Node Bl(Node n) { if (!ch) return n; if (!B(n)) return n; if (R(n.l) && R(n.l.l)) { n = RtR(n); n.l.b = true; } else if (R(n.l) && R(n.l.r)) { n = RtLR(n); n.l.b = true; } else if (R(n.r) && R(n.r.l)) { n = RtRL(n); n.r.b = true; } else if (R(n.r) && R(n.r.r)) { n = RtL(n); n.r.b = true; } else ch = false; return n; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public void Remove(T x) { r = Rm(r, x); if (r != null) r.b = true; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            Node Rm(Node n, T x) { if (n == null) { ch = false; return n; } var r = c(x, n.v); if (r < 0) { n.l = Rm(n.l, x); return BlL(n); } if (r > 0) { n.r = Rm(n.r, x); return BlR(n); } if (n.l == null) { ch = n.b; return n.r; } n.l = RmM(n.l); n.v = lm; return BlL(n); }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            Node RmM(Node n) { if (n.r != null) { n.r = RmM(n.r); return BlR(n); } lm = n.v; ch = n.b; return n.l; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            Node BlL(Node n) { if (!ch) return n; if (B(n.r) && R(n.r.l)) { var b = n.b; n = RtRL(n); n.b = b; n.l.b = true; ch = false; } else if (B(n.r) && R(n.r.r)) { var b = n.b; n = RtL(n); n.b = b; n.r.b = true; n.l.b = true; ch = false; } else if (B(n.r)) { ch = n.b; n.b = true; n.r.b = false; } else { n = RtL(n); n.b = true; n.l.b = false; n.l = BlL(n.l); ch = false; } return n; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            Node BlR(Node n) { if (!ch) return n; if (B(n.l) && R(n.l.r)) { var b = n.b; n = RtLR(n); n.b = b; n.r.b = true; ch = false; } else if (B(n.l) && R(n.l.l)) { var b = n.b; n = RtR(n); n.b = b; n.l.b = true; n.r.b = true; ch = false; } else if (B(n.l)) { ch = n.b; n.b = true; n.l.b = false; } else { n = RtR(n); n.b = true; n.r.b = false; n.r = BlR(n.r); ch = false; } return n; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public bool Have(T x) { var t = FindUpper(x); return t.Item1 && t.Item2.CompareTo(x) == 0; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public Tuple<bool, T> FindUpper(T x, bool findSame = true) { var v = FU(r, x, findSame); return v == null ? Tuple.Create(false, default(T)) : v; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            Tuple<bool, T> FU(Node n, T x, bool s) { if (n == null) return null; var r = c(x, n.v); if (r < 0) { var v = FU(n.l, x, s); return v == null ? Tuple.Create(true, n.v) : v; } if (r > 0 || !s && r == 0) return FU(n.r, x, s); return Tuple.Create(true, n.v); }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public Tuple<bool, T> FindLower(T x, bool findSame = true) { var v = FL(r, x, findSame); return v == null ? Tuple.Create(false, default(T)) : v; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            Tuple<bool, T> FL(Node n, T x, bool s) { if (n == null) return null; var r = c(x, n.v); if (r < 0 || !s && r == 0) return FL(n.l, x, s); if (r > 0) { var v = FL(n.r, x, s); return v == null ? Tuple.Create(true, n.v) : v; } return Tuple.Create(true, n.v); }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public T Min() { Node n = r, p = null; while (n != null) { p = n; n = n.l; } return p == null ? default(T) : p.v; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public T Max() { Node n = r, p = null; while (n != null) { p = n; n = n.r; } return p == null ? default(T) : p.v; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public bool Any() => r != null;
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public int CountSlow() => L(r).Count();
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public IEnumerable<T> List() => L(r);
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            IEnumerable<T> L(Node n) { if (n == null) yield break; foreach (var i in L(n.l)) yield return i; yield return n.v; foreach (var i in L(n.r)) yield return i; }
        }
        class Dict<K, V> : Dictionary<K, V>
        {
            new public V this[K i] { get { V v; return TryGetValue(i, out v) ? v : base[i] = default(V); } set { base[i] = value; } }
        }
        class Deque<T>
        {
            T[] b; int o, c;
            public int Count;
            public T this[int i] { get { return b[gi(i)]; } set { b[gi(i)] = value; } }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public Deque(int cap = 16) { b = new T[c = cap]; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            int gi(int i) { if (i >= c) throw new Exception(); var r = o + i; return r >= c ? r - c : r; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public void PushFront(T x) { if (Count == c) e(); if (--o < 0) o += b.Length; b[o] = x; ++Count; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public T PopFront() { if (Count-- == 0) throw new Exception(); var r = b[o++]; if (o >= c) o -= c; return r; }
            public T Front => b[o];
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public void PushBack(T x) { if (Count == c) e(); var i = o + Count++; b[i >= c ? i - c : i] = x; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public T PopBack() { if (Count == 0) throw new Exception(); return b[gi(--Count)]; }
            public T Back => b[gi(Count - 1)];
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            void e() { T[] nb = new T[c << 1]; if (o > c - Count) { var l = b.Length - o; Array.Copy(b, o, nb, 0, l); Array.Copy(b, 0, nb, l, Count - l); } else Array.Copy(b, o, nb, 0, Count); b = nb; o = 0; c <<= 1; }
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;

namespace CodeForces
{
    class Program
    {
        static void Main(string[] args)
        {
            var arr = Console.ReadLine().Split(' ');
            var p0 = Int32.Parse(arr[0]);
            var t0 = long.Parse(arr[1]);
            arr = Console.ReadLine().Split(' ');
            var p1 = Int32.Parse(arr[0]);
            var t1 = long.Parse(arr[1]);
            arr = Console.ReadLine().Split(' ');
            var h = Int32.Parse(arr[0]);
            var s = Int32.Parse(arr[1]);
            Console.WriteLine(GetMinCost(t0, t1, p0, p1, s, h));

            // Test();

            // BruteGetMaxVal("110000");
        }

        private static long GetMinCost(long t0, long t1, int p0, int p1, int s, int h)
        {
            var bags = new List<(int,long)>
            {
                (p0-s,t0),
                (p1-s,t1)
            };
            var allCost0 = (h/(p0-s) + 1) * t0;
            var allCost1 = (h/(p1-s) + 1) * t1;
            var maxCost = allCost0<=allCost1?allCost0:allCost1;
            var damage = 0;
            var t0Count = 1;
            while(damage < h && t0 * t0Count < maxCost)
            {
                if (t0 * t0Count >= t1)
                {
                    damage = (t0Count-1) * (p0 - s) +
                        (int)(t0 * t0Count / t1 - 1) * (p1 - s) +
                        (p0 + p1 -s);
                    bags.Add((damage, t0 * t0Count));
                }
                else
                {
                    damage = t0Count * (p0-s);
                }
                t0Count++;
            }

            damage = 0;
            var t1Count = 1;
            while (damage < h && t1 * t1Count < maxCost)
            {
                if (t1 * t1Count >= t0)
                {
                    damage = (t1Count-1) * (p1 - s) +
                        (int)(t1 * t1Count / t0 - 1) * (p0 - s) +
                        (p0 + p1 -s);
                    bags.Add((damage, t1 * t1Count));
                }
                else
                {
                    damage = t1Count * (p1-s);
                }
                t1Count++;
            }
            return GetMinCost(h, bags);
        }

        private static long GetMinCost(int h, List<(int, long)> bags)
        {
            var newBags = new List<(int, long)>();
            foreach(var (damage, cost) in bags)
            {
                var newDamage = damage;
                var newCost = cost;
                while(newDamage < h + damage)
                {
                    newBags.Add((newDamage, newCost));
                    newDamage<<=1;
                    newCost<<=1;
                }
            }
            return Get01MinCost(h, newBags);
        }

        private static long Get01MinCost(int h, List<(int, long)> bags)
        {
            var n = bags.Count;
            var dp = new long[h+1];
            for(var i = 1;i<=h;i++)
            {
                dp[i] = long.MaxValue;
            }
            foreach(var (damage, cost) in bags)
            {
                var jBegin = h - damage;
                if (jBegin < 0) jBegin = 0;
                for(var j = jBegin;j<=h;j++)
                {
                    if (dp[j] != long.MaxValue && dp[j] + cost < dp[h])
                    {
                        dp[h] = dp[j] + cost;
                    }
                }
                for(var j= h - damage-1;j>=0;j--)
                {
                    if (dp[j] != long.MaxValue && dp[j] + cost < dp[j+ damage])
                    {
                        dp[j+ damage] = dp[j] + cost;
                    }
                }

            }
            return dp[h];
        }

    }
}


using System;
using System.Collections.Generic;
using System.Text;

namespace Contest3
{
    class Program
    {
        static void Main(string[] args)
        {
            var temp = Console.ReadLine().Split(' ');
            long n = long.Parse(temp[0]);
            long a = long.Parse(temp[1]);
            long b = long.Parse(temp[2]);
            long c = long.Parse(temp[3]);
            long l = 0;
            n *= 2;
            for (long i = 0; i <= c; i++)
                for (long j = 0; j <= b; j++)
                {
                    long k = n - i * 4 - 2 * j;

                    if ((k >= 0) && (k <= a))
                        l++;
                }
            Console.WriteLine(l);

        }
    }
}


using System;
using System.IO;
using System.Text;

namespace Cola
{
    internal class Program
    {
        private static readonly StreamReader reader = new StreamReader(Console.OpenStandardInput(1024*10), Encoding.ASCII, false, 1024*10);
        private static readonly StreamWriter writer = new StreamWriter(Console.OpenStandardOutput(1024*10), Encoding.ASCII, 1024*10);

        private static void Main(string[] args)
        {
            int n = Next(), a = Next(), b = Next(), c = Next();

            int count = 0;
            for (int aa = 0; aa <= a; aa += 2)
            {
                for (int cc = 0; cc <= c; cc++)
                {
                    int bb = n - aa/2 - 2*cc;
                    if (bb >= 0 && bb <= b)
                        count++;
                }
            }

            writer.WriteLine(count);
            writer.Flush();
        }

        private static int Next()
        {
            int c;
            int res = 0;
            do
            {
                c = reader.Read();
                if (c == -1)
                    return res;
            } while (c < '0' || c > '9');
            res = c - '0';
            while (true)
            {
                c = reader.Read();
                if (c < '0' || c > '9')
                    return res;
                res *= 10;
                res += c - '0';
            }
        }
    }
}


using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Collections.Generic;
using System.Diagnostics;
using System.Numerics;
using Enu = System.Linq.Enumerable;

class Program
{
    static readonly int Mod = (int)1e9 + 7;

    public void Solve()
    {
        int N = Reader.Int();
        int K = Reader.Int();
        long[] Y = new long[K + 2];

        for (int i = 1; i < Y.Length; i++)
            Y[i] = (Y[i - 1] + ModPower(i, K, Mod)) % Mod;

        long ans = new LagrangeInterpolation(Y, Mod).Get(N);
        Console.WriteLine(ans);
        Console.ReadLine();
    }

    class LagrangeInterpolation
    {
        readonly int N;
        readonly long M;
        readonly long[] Y, C;

        public LagrangeInterpolation(long[] Y, long mod)
        {
            this.N = Y.Length - 1;
            this.M = mod;
            this.Y = Y;
            this.C = new long[N + 1];
            long q = 1;
            for (int i = 1; i <= N; i++)
                q = q * Mod(-i) % mod;
            C[0] = Mod(Y[0] * ModInverse(q, mod));
            for (int i = 1; i <= N; i++)
            {
                q = Mod(q * ModInverse(-N + (i - 1), mod));
                q = Mod(q * i);
                C[i] = Mod(Y[i] * ModInverse(q, mod));
            }
        }

        public long Get(long x)
        {
            if (x <= N) return Y[x];
            long fraq = 1;
            for (int i = 0; i <= N; i++)
                fraq = Mod(fraq * (x - i));
            long res = 0;
            for (int i = 0; i <= N; i++)
            {
                res += Mod(Mod(C[i] * fraq) * ModInverse(x - i, M));
                if (res >= M) res -= M;
            }
            return res;
        }

        long Mod(long x)
        {
            if (x >= M) return x % M;
            else if (x < 0) return (x % M + M);
            else return x;
        }
    }

    static long ModPower(long x, long n, long mod) // x ^ n
    {
        long res = 1;
        while (n > 0)
        {
            if ((n & 1) == 1) res = (res * x) % mod;
            x = (x * x) % mod;
            n >>= 1;
        }
        return res;
    }
    static long ModInverse(long N, long mod)
    {
        long x = 0, y = 0;
        N = (N % mod + mod) % mod;
        ExtGCD(N, mod, ref x, ref y);
        return (x % mod + mod) % mod;
    }
    static long ExtGCD(long a, long b, ref long x, ref long y)
    {
        if (b == 0) { x = 1; y = 0; return a; }
        long res = ExtGCD(b, a % b, ref y, ref x);
        y -= (a / b) * x;
        return res;
    }
}

class Entry { static void Main() { new Program().Solve(); } }
class Reader
{
    private static TextReader reader = Console.In;
    private static readonly char[] separator = { ' ' };
    private static readonly StringSplitOptions op = StringSplitOptions.RemoveEmptyEntries;
    private static string[] A = new string[0];
    private static int i;
    private static void Init() { A = new string[0]; }
    public static void Set(TextReader r) { reader = r; Init(); }
    public static void Set(string file) { reader = new StreamReader(file); Init(); }
    public static bool HasNext() { return CheckNext(); }
    public static string String() { return Next(); }
    public static int Int() { return int.Parse(Next()); }
    public static long Long() { return long.Parse(Next()); }
    public static double Double() { return double.Parse(Next()); }
    public static int[] IntLine() { return Array.ConvertAll(Split(Line()), int.Parse); }
    public static int[] IntArray(int N) { return Enu.Range(0, N).Select(i => Int()).ToArray(); }
    public static int[][] IntTable(int H) { return Enu.Range(0, H).Select(i => IntLine()).ToArray(); }
    public static string[] StringArray(int N) { return Enu.Range(0, N).Select(i => Next()).ToArray(); }
    public static string Line() { return reader.ReadLine().Trim(); }
    private static string[] Split(string s) { return s.Split(separator, op); }
    private static string Next() { CheckNext(); return A[i++]; }
    private static bool CheckNext()
    {
        if (i < A.Length) return true;
        string line = reader.ReadLine();
        if (line == null) return false;
        if (line == "") return CheckNext();
        A = Split(line);
        i = 0;
        return true;
    }
}


#region Usings
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using static System.Array;
using static System.Math;

// ReSharper disable InconsistentNaming
#pragma warning disable CS0675
#endregion

partial class Solution
{
	#region Variables
	const int MOD = 1000000007;
	const int FactCache = 1000;
	const long BIG = long.MaxValue >> 15;

	#endregion

	public static void Main()
	{
		var input = new StreamReader(Console.OpenStandardInput());
		var output = new StreamWriter(Console.OpenStandardOutput());

		long[] array = ConvertAll(input.ReadLine().Split(), long.Parse);
		long n = array[0];
		long k = array[1];

		var y = new List<long>();
		long sum = 0;
		y.Add(sum);
		for (int i = 0; i <= k; i++)
		{
			sum = (sum + ModPow(i + 1, k));
			if (sum >= MOD) sum -= MOD;
			y.Add(sum);
		}

		if (n < y.Count)
			output.WriteLine(y[(int)n]);
		else
			output.WriteLine(Lagrange(y, n));
		output.Flush();
	}

	static long Lagrange(List<long> y, long x)
	{
		long ans = 0;
		long k = 1;
		for (int j = 1; j < y.Count; j++)
		{
			k = (k * (x - j)) % MOD;
			k = MOD - Div(k, j);
		}

		for (int i = 0; i < y.Count; i++)
		{
			ans = (ans + y[i] * k) % MOD;
			if (i + 1 >= y.Count) break;
			k = k * Div(x - i, x - (i + 1)) % MOD * Div(i - y.Count + 1, i + 1) % MOD;
		}

		return Fix(ans);
	}

	#region Library
	#region Mod Math

	static int[] _inverse;
	static long Inverse(long n)
	{
		long result;

		if (_inverse == null)
			_inverse = new int[1000];

		if (n >= 0 && n < _inverse.Length && (result = _inverse[n]) != 0)
			return result - 1;

		result = InverseDirect((int)n);
		if (n >= 0 && n < _inverse.Length)
			_inverse[n] = (int)(result + 1);
		return result;
	}

	public static int InverseDirect(int a)
	{
		if (a < 0) return -InverseDirect(-a);
		int t = 0, r = MOD, t2 = 1, r2 = a;
		while (r2 != 0)
		{
			var q = r / r2;
			t -= q * t2;
			r -= q * r2;

			if (r != 0)
			{
				q = r2 / r;
				t2 -= q * t;
				r2 -= q * r;
			}
			else
			{
				r = r2;
				t = t2;
				break;
			}
		}
		return r <= 1 ? (t >= 0 ? t : t + MOD) : -1;
	}

	static long Mult(long left, long right) =>
		(left * right) % MOD;

	static long Div(long left, long divisor) =>
		left * Inverse(divisor) % MOD;

	static long Add(long x, long y) =>
		(x += y) >= MOD ? x - MOD : x;

	static long Subtract(long x, long y) => (x -= y) < 0 ? x + MOD : x;

	static long Fix(long n) => (n %= MOD) >= 0 ? n : n + MOD;

	static long ModPow(long n, long p, long mod = MOD)
	{
		long b = n;
		long result = 1;
		while (p != 0)
		{
			if ((p & 1) != 0)
				result = (result * b) % mod;
			p >>= 1;
			b = (b * b) % mod;
		}
		return result;
	}

	static List<long> _fact;

	static long Fact(int n)
	{
		if (_fact == null) _fact = new List<long>(FactCache) { 1 };
		for (int i = _fact.Count; i <= n; i++)
			_fact.Add(Mult(_fact[i - 1], i));
		return _fact[n];
	}

	static long[] _ifact = new long[0];
	static long InverseFact(int n)
	{
		long result;
		if (n < _ifact.Length && (result = _ifact[n]) != 0)
			return result;

		var inv = Inverse(Fact(n));
		if (n >= _ifact.Length) Resize(ref _ifact, _fact.Capacity);
		_ifact[n] = inv;
		return inv;
	}

	static long Fact(int n, int m)
	{
		var fact = Fact(n);
		if (m < n) fact = fact * InverseFact(n - m) % MOD;
		return fact;
	}

	static long Comb(int n, int k)
	{
		if (k <= 1) return k == 1 ? n : k == 0 ? 1 : 0;
		return Mult(Mult(Fact(n), InverseFact(k)), InverseFact(n - k));
	}

	public static long Combinations(long n, int k)
	{
		if (k <= 0) return k == 0 ? 1 : 0;  // Note: n<0 -> 0 unless k=0
		if (k + k > n) return Combinations(n, (int)(n - k));

		var result = InverseFact(k);
		for (long i = n - k + 1; i <= n; i++) result = result * i % MOD;
		return result;
	}
	#endregion

	#region Common

	public static int Gcd(int n, int m)
	{
		while (true)
		{
			if (m == 0) return n >= 0 ? n : -n;
			n %= m;
			if (n == 0) return m >= 0 ? m : -m;
			m %= n;
		}
	}

	#endregion

	#region Main

	#endregion
	#endregion
}


using System.Collections.Generic;
using System.Linq;
using System;

public class Solution
{
    public static void Main()
    {

        int[] A = Array.ConvertAll(Console.ReadLine().Split(' '), m => Convert.ToInt32(m));
        int W = A[0], H = A[1];
        int[] B = Array.ConvertAll(Console.ReadLine().Split(' '), m => Convert.ToInt32(m));
        int w1 = B[0], h1 = B[1];
        int[] C = Array.ConvertAll(Console.ReadLine().Split(' '), m => Convert.ToInt32(m));
        int w2 = C[0], h2 = C[1];

       while(H > 0)
        {
            W += H;

            if (H == h1)
                W -= w1;

            if (H == h2)
                W -= w2;

            if (W < 0)
                W = 0;

            H--;
        }

        Console.WriteLine(W);

    }
}


using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace codeforce
{
    class Program
    {
        static void Main(string[] args)
        {
            string temp = Console.ReadLine();
            string[] splitted = temp.Split(' ');
            int w = Convert.ToInt32(splitted[0]);
            int h = Convert.ToInt32(splitted[1]);
            temp = Console.ReadLine();
            splitted = temp.Split(' ');
            int u1 = Convert.ToInt32(splitted[0]);
            int d1 = Convert.ToInt32(splitted[1]);
            temp = Console.ReadLine();
            splitted = temp.Split(' ');
            int u2 = Convert.ToInt32(splitted[0]);
            int d2 = Convert.ToInt32(splitted[1]);

            for (int i = h; i > 0; i--)
            {
                w += i;
                if (i == d1)
                {
                    w -= u1;
                    if (w < 0) w = 0;
                }
                if (i == d2)
                {
                    w -= u2;
                    if (w < 0) w = 0;
                }
            }
            Console.WriteLine(w);
        }
    }
}


using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.IO;

class Program
{
    long[, , , ,] dp;
    void solve()
    {
        int n = nextInt();
        int t = nextInt();
        dp = new long[5, 5, n, t+1,t];
        for (int i = 0; i < 5; i++)
            for (int j = 0; j < 5; j++)
                for (int k = 0; k < n; k++)
                    for (int r = 0; r <= t; r++)
                        for (int s = 0; s < t; s++)
                            dp[i, j, k, r, s] = -1;
        long ret = 0;
        for(int y1=1;y1<=4;y1++)
            for (int y2 = y1; y2 <= 4; y2++)
            {
                if (y1 == y2)
                    continue;
                int a = t;
                int b = t - 1;
                ret += go(y1, y2, n - 2, a, b);
            }
        Console.WriteLine(ret);
    }

    private long go(int y1, int y2, int rem, int a, int b)
    {
        if (a < 0 || b < 0)
            return 0;
        if (rem == 0)
        {
            if (a == 0 && b == 0)
                return 1;
            else
                return 0;
        }
        if (dp[y1, y2, rem, a, b] != -1)
            return dp[y1, y2, rem, a, b];
        long ret = 0;
        for (int y3 = 1; y3 <= 4; y3++)
        {
            if (y3 == y2)
                continue;
            if (y2 > y1 && y2 > y3)
            {
                ret += go(y2, y3, rem - 1, a - 1, b);
            }
            else if (y2 < y1 && y2 < y3)
                ret += go(y2, y3, rem - 1, a, b - 1);
            else
                ret += go(y2, y3, rem - 1, a, b);
        }
        return dp[y1, y2, rem, a, b]=ret;
    }
    //

    string[] inputLine = new string[0];
    int inputInd = 0;
    string nextLine()
    {
        return Console.ReadLine();
    }
    void readInput()
    {
        if (inputInd != inputLine.Length)
            throw new Exception();
        inputInd = 0;
        inputLine = Console.ReadLine().Split();

    }
    int nextInt()
    {
        if (inputInd == inputLine.Length)
            readInput();
        return int.Parse(inputLine[inputInd++]);
    }
    long nextLong()
    {
        if (inputInd == inputLine.Length)
            readInput();
        return long.Parse(inputLine[inputInd++]);
    }
    double nextDouble()
    {
        if (inputInd == inputLine.Length)
            readInput();
        return double.Parse(inputLine[inputInd++]);
    }
    string nextString()
    {
        if (inputInd == inputLine.Length)
            readInput();
        return inputLine[inputInd++];
    }
    static void Main(string[] args)
    {
        new Program().solve();
    }
}


using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;

// (づ°ω°)づﾐe★゜・。。・゜゜・。。・゜☆゜・。。・゜゜・。。・゜
public class Solver
{
    public void Solve()
    {
        int n = ReadInt();
        int m = ReadInt();

        var dp = new long[m + 1, m, 4, 4];
        dp[0, 0, 0, 0] = 1;
        for (int i = 0; i < n; i++)
        {
            var ndp = new long[m + 1, m, 4, 4];
            for (int t = 0; t <= m; t++)
                for (int v = 0; v < m; v++)
                    for (int pp = 0; pp < 4; pp++)
                        for (int p = 0; p < 4; p++)
                            for (int d = 0; d < 4; d++)
                                if (i == 0 || d != p)
                                {
                                    int nt = t;
                                    if (i > 1 && pp < p && p > d)
                                        nt++;
                                    int nv = v;
                                    if (i > 1 && pp > p && p < d)
                                        nv++;
                                    if (nt <= m && nv < m)
                                        ndp[nt, nv, p, d] += dp[t, v, pp, p];
                                }
            dp = ndp;
        }

        long ans = 0;
        for (int i = 0; i < 4; i++)
            for (int j = 0; j < 4; j++)
                ans += dp[m, m - 1, i, j];
        Write(ans);
    }

    #region Main

    protected static TextReader reader;
    protected static TextWriter writer;
    static void Main()
    {
#if DEBUG
        reader = new StreamReader("..\\..\\input.txt");
        //reader = new StreamReader(Console.OpenStandardInput());
        writer = Console.Out;
        //writer = new StreamWriter("..\\..\\output.txt");
#else
        reader = new StreamReader(Console.OpenStandardInput());
        writer = new StreamWriter(Console.OpenStandardOutput());
        //reader = new StreamReader("input.txt");
        //writer = new StreamWriter("output.txt");
#endif
        try
        {
            new Solver().Solve();
            //var thread = new Thread(new Solver().Solve, 1024 * 1024 * 128);
            //thread.Start();
            //thread.Join();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
#if DEBUG
#else
            throw;
#endif
        }
        reader.Close();
        writer.Close();
    }

    #endregion

    #region Read / Write
    private static Queue<string> currentLineTokens = new Queue<string>();
    private static string[] ReadAndSplitLine() { return reader.ReadLine().Split(new[] { ' ', '\t', }, StringSplitOptions.RemoveEmptyEntries); }
    public static string ReadToken() { while (currentLineTokens.Count == 0)currentLineTokens = new Queue<string>(ReadAndSplitLine()); return currentLineTokens.Dequeue(); }
    public static int ReadInt() { return int.Parse(ReadToken()); }
    public static long ReadLong() { return long.Parse(ReadToken()); }
    public static double ReadDouble() { return double.Parse(ReadToken(), CultureInfo.InvariantCulture); }
    public static int[] ReadIntArray() { return ReadAndSplitLine().Select(int.Parse).ToArray(); }
    public static long[] ReadLongArray() { return ReadAndSplitLine().Select(long.Parse).ToArray(); }
    public static double[] ReadDoubleArray() { return ReadAndSplitLine().Select(s => double.Parse(s, CultureInfo.InvariantCulture)).ToArray(); }
    public static int[][] ReadIntMatrix(int numberOfRows) { int[][] matrix = new int[numberOfRows][]; for (int i = 0; i < numberOfRows; i++)matrix[i] = ReadIntArray(); return matrix; }
    public static int[][] ReadAndTransposeIntMatrix(int numberOfRows)
    {
        int[][] matrix = ReadIntMatrix(numberOfRows); int[][] ret = new int[matrix[0].Length][];
        for (int i = 0; i < ret.Length; i++) { ret[i] = new int[numberOfRows]; for (int j = 0; j < numberOfRows; j++)ret[i][j] = matrix[j][i]; } return ret;
    }
    public static string[] ReadLines(int quantity) { string[] lines = new string[quantity]; for (int i = 0; i < quantity; i++)lines[i] = reader.ReadLine().Trim(); return lines; }
    public static void WriteArray<T>(IEnumerable<T> array) { writer.WriteLine(string.Join(" ", array)); }
    public static void Write(params object[] array) { WriteArray(array); }
    public static void WriteLines<T>(IEnumerable<T> array) { foreach (var a in array)writer.WriteLine(a); }
    private class SDictionary<TKey, TValue> : Dictionary<TKey, TValue>
    {
        public new TValue this[TKey key]
        {
            get { return ContainsKey(key) ? base[key] : default(TValue); }
            set { base[key] = value; }
        }
    }
    private static T[] Init<T>(int size) where T : new() { var ret = new T[size]; for (int i = 0; i < size; i++)ret[i] = new T(); return ret; }
    #endregion
}


using System;

namespace CodeForces
{
    class Program
    {
        static void Main(string[] args)
        {
            string answer = "Yes";
            string[] num = Console.ReadLine().Split(' ');
            int a = int.Parse(num[0]);
            int b = int.Parse(num[1]);
            int c = int.Parse(num[2]);
            num = Console.ReadLine().Split(' ');
            int x = int.Parse(num[0]);
            int y = int.Parse(num[1]);
            int z = int.Parse(num[2]);
            if (a + b + c < x + y + z)
                answer = "No";
            else
            {
                while (a < x)
                {
                    if ((b - y) >= 2)
                    {
                        b -= 2;
                        a++;
                    }
                    else
                    {
                        if ((c - z) >= 2)
                        {
                            c -= 2;
                            a++;
                        }
                        else
                        {
                            answer = "No";
                            break;
                        }
                    }
                }
                if (answer != "No")
                {
                    while (b < y)
                    {
                        if ((a - x) >= 2)
                        {
                            a -= 2;
                            b++;
                        }
                        else
                        {
                            if ((c - z) >= 2)
                            {
                                c -= 2;
                                b++;
                            }
                            else
                            {
                                answer = "No";
                                break;
                            }
                        }
                    }
                }
                if (answer != "No")
                {
                    while (c < z)
                    {
                        if ((a - x) >= 2)
                        {
                            a -= 2;
                            c++;
                        }
                        else
                        {
                            if ((b - y) >= 2)
                            {
                                b -= 2;
                                c++;
                            }
                            else { answer = "No"; break; }
                        }
                    }

                }
            }
            Console.WriteLine(answer);
        }
    }
}


/*
 * Created by SharpDevelop.
 * Date: 21.12.2015
 * Time: 12:49
 *
 */

using System;

namespace Shape
{
    class Program
    {

        static void Main(string[] args)
        {
        	string ss = Console.ReadLine ();
        	string [] s = ss.Split (' ');
        	int a = int.Parse (s [0]);
        	int b = int.Parse (s [1]);
        	int c = int.Parse (s [2]);

        	ss = Console.ReadLine ();
        	string [] t = ss.Split (' ');
        	int x = int.Parse (t [0]);
        	int y = int.Parse (t [1]);
        	int z = int.Parse (t [2]);

        	int kp=0, km=0;
        	if ( a > x )
        		kp += (a - x)/2;
        	else
        		km += x - a;
        	if ( b > y )
        		kp += (b - y)/2;
        	else
        		km += y - b;
        	if ( c > z )
        		kp += (c - z)/2;
        	else
        		km += z - c;

        	if ( kp >= km )
        		Console.WriteLine ("Yes");
        	else
        		Console.WriteLine ("No");

 //           Console.ReadKey ();
        }
    }
}


using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;

namespace ReadWriteTemplate
{
    public static class Solver
    {
        private static void SolveCase()
        {
            var s = ReadLine();
            int n = s.Length;
            for (int i = n; i >= 0; i--)
            {
                bool isPal = true;
                for (int j = 0; j < i; j++)
                {
                    if (s[j] != s[i - j - 1])
                    {
                        isPal = false;
                        break;
                    }
                }
                if (!isPal)
                {
                    Writer.WriteLine(i);
                    return;
                }
            }
            Writer.WriteLine(0);
        }

        public static void Solve()
        {
            SolveCase();

            /*var sw = Stopwatch.StartNew();*/

            /*int T = ReadInt();
            for (int i = 0; i < T; i++)
            {
                Writer.Write("Case #{0}: ", i + 1);
                SolveCase();
            }*/

            /*sw.Stop();
            Console.WriteLine(sw.ElapsedMilliseconds);*/
        }

        public static void Main()
        {
            Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

#if DEBUG
            //Reader = Console.In; Writer = Console.Out;
            Reader = File.OpenText("input.txt"); Writer = File.CreateText("output.txt");
#else
            Reader = Console.In; Writer = Console.Out;
#endif

            Solve();
            /*Thread thread = new Thread(Solve, 64 * 1024 * 1024);
            thread.CurrentCulture = CultureInfo.InvariantCulture;
            thread.Start();
            thread.Join();*/

            Reader.Close();
            Writer.Close();
        }

        public static IOrderedEnumerable<TSource> OrderByWithShuffle<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
        {
            return source.Shuffle().OrderBy(keySelector);
        }

        public static T[] Shuffle<T>(this IEnumerable<T> source)
        {
            T[] result = source.ToArray();
            Random rnd = new Random();
            for (int i = result.Length - 1; i >= 1; i--)
            {
                int k = rnd.Next(i + 1);
                T tmp = result[k];
                result[k] = result[i];
                result[i] = tmp;
            }
            return result;
        }

        #region Read/Write

        private static TextReader Reader;

        private static TextWriter Writer;

        private static Queue<string> CurrentLineTokens = new Queue<string>();

        private static string[] ReadAndSplitLine()
        {
            return Reader.ReadLine().Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
        }

        public static string ReadToken()
        {
            while (CurrentLineTokens.Count == 0)
                CurrentLineTokens = new Queue<string>(ReadAndSplitLine());
            return CurrentLineTokens.Dequeue();
        }

        public static string ReadLine()
        {
            return Reader.ReadLine();
        }

        public static int ReadInt()
        {
            return int.Parse(ReadToken());
        }

        public static long ReadLong()
        {
            return long.Parse(ReadToken());
        }

        public static double ReadDouble()
        {
            return double.Parse(ReadToken(), CultureInfo.InvariantCulture);
        }

        public static int[] ReadIntArray()
        {
            return ReadAndSplitLine().Select(int.Parse).ToArray();
        }

        public static long[] ReadLongArray()
        {
            return ReadAndSplitLine().Select(long.Parse).ToArray();
        }

        public static double[] ReadDoubleArray()
        {
            return ReadAndSplitLine().Select(s => double.Parse(s, CultureInfo.InvariantCulture)).ToArray();
        }

        public static int[][] ReadIntMatrix(int numberOfRows)
        {
            int[][] matrix = new int[numberOfRows][];
            for (int i = 0; i < numberOfRows; i++)
                matrix[i] = ReadIntArray();
            return matrix;
        }

        public static string[] ReadLines(int quantity)
        {
            string[] lines = new string[quantity];
            for (int i = 0; i < quantity; i++)
                lines[i] = Reader.ReadLine().Trim();
            return lines;
        }

        public static void WriteArray<T>(IEnumerable<T> array)
        {
            Writer.WriteLine(string.Join(" ", array));
        }

        #endregion
    }
}


using System;
namespace SolutionsForCodeforces
{
    class Program
    {
        static void Main(string[] args)
        {
            string MyString = Console.ReadLine();
            if (!IsPalindrom(MyString))
            {
                Console.WriteLine(MyString.Length);
                return;
            }
            else
            {
                MyString = MyString.Remove(0, 1);
                if (!IsPalindrom(MyString))
                {
                    Console.WriteLine(MyString.Length);
                    return;
                }
                else Console.WriteLine("0");
            }
        }
        static bool IsPalindrom(string s)
        {
            var Array = s.ToCharArray();
            var ReversedArray = (char[])Array.Clone();
            System.Array.Reverse(ReversedArray);
            bool IsGood = true;
            for (int i = 0; i < Array.Length; i++)
            {
                if (Array[i] != ReversedArray[i])
                {
                    IsGood = false;
                }
            }
            return IsGood;
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;

namespace CodeForces
{
    class Program
    {
        static void Main(string[] args)
        {

            var n = Int32.Parse(Console.ReadLine());

            Console.WriteLine(GetVal(n));
        }

        const int MOD_VAL = 1000000007;
        private static int GetVal(int n)
        {
            var primes = GetAllPrimes(n);
            var res = 0;
            var primeCache = GetPrimeCache(primes, n);
            var dfsSolver = new DFSSolver(primeCache);
            for(var i = 1;i<=n-2;i++)
            {
                var primeFactors = GetPrimeFactors(i, primes);
                var primeMap = new Dictionary<int,int>();
                foreach(var (prime, primeCnt) in primeFactors)
                {
                    primeMap[prime] = primeCnt;
                }
                dfsSolver.SetPrimeMap(primeMap);
                dfsSolver.SetPrimeFactors(GetPrimeFactors(n-i, primes));
                res = (int)((res + (long)dfsSolver.GetRes()*i ) % MOD_VAL);
            }
            return res;
        }

        private class DFSSolver
        {
            private int _res;
            private Dictionary<int,int> _primeMap;
            private List<(int,int)> _primeFactors;

            private Dictionary<int, int[]> _primeCache;
            public DFSSolver(Dictionary<int, int[]> primeCache)
            {
                _primeCache = primeCache;
            }

            public void SetPrimeMap(Dictionary<int,int> primeMap)
            {
                _primeMap = primeMap;
            }

            public void SetPrimeFactors(List<(int,int)> primeFactors)
            {
                _primeFactors = primeFactors;
            }

            public int GetRes()
            {
                _res = 0;
                DFS(0,1);
                var tmp = 1;
                foreach(var (prime, cnt) in _primeFactors)
                {
                    if(_primeMap.ContainsKey(prime))
                    {
                        if(cnt > _primeMap[prime])
                        {
                            tmp*= _primeCache[prime][cnt-_primeMap[prime]];
                        }
                    }
                    else
                    {
                        tmp*= _primeCache[prime][cnt];
                    }
                }
                _res-=tmp;
                if (_res < MOD_VAL) _res+=MOD_VAL;
                return _res;
            }

            private void DFS(int index, int val)
            {
                if(index == _primeFactors.Count)
                {
                    _res = (_res + val) % MOD_VAL;
                    return;
                }
                var prime = _primeFactors[index].Item1;
                var cnt = _primeFactors[index].Item2;
                for(var i = 0;i<= cnt;i++)
                {
                    var append = 1;
                    if(_primeMap.ContainsKey(prime))
                    {
                        if(i > _primeMap[prime])
                        {
                            append = _primeCache[prime][i - _primeMap[prime]];
                        }
                    }
                    else
                    {
                        append = _primeCache[prime][i];
                    }

                    if (i < cnt)
                    {
                        append = append * (prime - 1) * _primeCache[prime][cnt-i-1];
                    }
                    DFS(index+1, (int)((long)val * append % MOD_VAL));
                }
            }
        }

        private static Dictionary<int, int[]> GetPrimeCache(List<int> primes, int n)
        {
            var primeCache = new Dictionary<int, int[]>();
            foreach(var prime in primes)
            {
                var list = new List<int>();
                list.Add(1);
                var tmp = prime;
                while(tmp <= n)
                {
                    list.Add(tmp);
                    tmp*=prime;
                }
                primeCache[prime] = list.ToArray();
            }
            return primeCache;
        }

        private static int GetLCM(int num0, int num1)
        {
            return (int)((long)num0 * num1 /GetGCD(num0, num1));
        }

        private static int GetGCD(int num0, int num1)
        {
            if (num0 < num1)
            {
                var tmp = num1;
                num1 = num0;
                num0 = tmp;
            }
            while (num1 > 0)
            {
                var tmp = num1;
                num1 = num0 % num1;
                num0 = tmp;
            }
            return num0;
        }

        static List<int> GetAllPrimes(int n)
        {
            var isNotPrimes = new bool[n+1];
            var primes = new List<int>();
            for(var i = 2;i<=n;i++)
            {
                if (!isNotPrimes[i])
                {
                    primes.Add(i);
                    var num = i * 2;
                    while(num <= n)
                    {
                        isNotPrimes[num]= true;
                        num+=i;
                    }
                }
            }
            return primes;
        }

        static List<(int,int)> GetPrimeFactors(int num, List<int> primes)
        {
            var primeFactors = new List<(int,int)>();
            foreach(var prime in primes)
            {
                if (num < prime * prime) break;
                var cnt = 0;
                while(num % prime == 0)
                {
                    cnt++;
                    num/=prime;
                }
                if (cnt > 0)
                {
                    primeFactors.Add((prime, cnt));
                }
            }
            if (num!=1)
            {
                primeFactors.Add((num, 1));
            }
            return primeFactors;
        }

        static int[] GetFactors(int num, List<int> primes)
        {
            return GetFactors(GetPrimeFactors(num, primes));
        }

        static int[] GetFactors(List<(int,int)> primeFactors)
        {
            var factorCnt = 1;
            foreach(var (_, cnt) in primeFactors)
            {
                factorCnt*=cnt+1;
            }
            var factors = new int[factorCnt];
            var preCnt = 1;
            var index = 1;
            factors[0] = 1;
            foreach(var (prime, cnt) in primeFactors)
            {
                var factor = prime;
                for(var i = 1;i<=cnt;i++)
                {
                    for(var j = 0;j<preCnt;j++)
                    {
                        factors[index++] = factors[j] * factor;
                    }
                    factor *= prime;
                }
                preCnt = index;
            }
            return factors;
        }

    }
}


using System;
using System.Linq;
using CompLib.Util;
using System.Threading;
using System.IO;
using System.Collections.Generic;
using System.Text;
using CompLib.Mathematics;

public class Program
{
    int N;
    List<int>[] Div;

    int[] Sieve;

    int[] S;

    public void Solve()
    {

        var sc = new Scanner();
        N = sc.NextInt();
        Div = new List<int>[N + 1];
        for (int i = 1; i <= N; i++)
        {
            Div[i] = new List<int>();
        }

        for (int i = 1; i <= N; i++)
        {
            for (int j = i; j <= N; j += i)
            {
                Div[j].Add(i);
            }
        }

        S = new int[N + 1];
        S[1] = 0;
        for (int i = 2; i <= N; i++)
        {
            S[i] = i - 1;
            foreach (int d in Div[i])
            {
                if (i == d) continue;
                // Console.WriteLine($"{S[i / d]}");
                S[i] -= S[d];
            }
        }

        //for (int i = 1; i < 20; i++)
        //{
        //    Console.WriteLine($"{i} {F2(i)} {S[i]}");
        //}

        ModInt ans = 0;
        for (int c = 1; c + 2 <= N; c++)
        {
            int sumAB = N - c;
            foreach (int gcdAB in Div[sumAB])
            {
                int d = sumAB / gcdAB;

                // a + b = d
                // gcd(a,b) = 1

                ans += S[d] * MathEx.LCM(c, gcdAB);
            }
        }

        Console.WriteLine(ans);

    }
    ModInt F2(int n)
    {
        int cnt = 0;
        for (int a = 1; a + 1 <= n; a++)
        {
            cnt += MathEx.GCD(a, n - a) == 1 ? 1 : 0;
        }
        return cnt;
    }

    public static void Main(string[] args) => new Program().Solve();
    // public static void Main(string[] args) => new Thread(new Program().Solve, 1 << 27).Start();
}

// https://bitbucket.org/camypaper/complib
namespace CompLib.Mathematics
{
    using System;
    using System.Collections.Generic;
    #region GCD LCM
    /// <summary>
    /// 様々な数学的関数の静的メソッドを提供します．
    /// </summary>
    public static partial class MathEx
    {
        /// <summary>
        /// 2 つの整数の最大公約数を求めます．
        /// </summary>
        /// <param name="n">最初の値</param>
        /// <param name="m">2 番目の値</param>
        /// <returns>2 つの整数の最大公約数</returns>
        /// <remarks>ユークリッドの互除法に基づき最悪計算量 O(log N) で実行されます．</remarks>
        public static int GCD(int n, int m) { return (int)GCD((long)n, m); }

        /// <summary>
        /// 2 つの整数の最大公約数を求めます．
        /// </summary>
        /// <param name="n">最初の値</param>
        /// <param name="m">2 番目の値</param>
        /// <returns>2 つの整数の最大公約数</returns>
        /// <remarks>ユークリッドの互除法に基づき最悪計算量 O(log N) で実行されます．</remarks>
        public static long GCD(long n, long m)
        {
            n = Math.Abs(n);
            m = Math.Abs(m);
            while (n != 0)
            {
                m %= n;
                if (m == 0) return n;
                n %= m;
            }
            return m;
        }

        /// <summary>
        /// 2 つの整数の最小公倍数を求めます．
        /// </summary>
        /// <param name="n">最初の値</param>
        /// <param name="m">2 番目の値</param>
        /// <returns>2 つの整数の最小公倍数</returns>
        /// <remarks>最悪計算量 O(log N) で実行されます．</remarks>
        public static long LCM(long n, long m) { return (n / GCD(n, m)) * m; }
    }
    #endregion
    #region PrimeSieve
    public static partial class MathEx
    {
        /// <summary>
        /// ある値までに素数表を構築します．
        /// </summary>
        /// <param name="max">最大の値</param>
        /// <param name="primes">素数のみを入れた数列が返される</param>
        /// <returns>0 から max までの素数表</returns>
        /// <remarks>エラトステネスの篩に基づき，最悪計算量 O(N loglog N) で実行されます．</remarks>
        public static bool[] Sieve(int max, List<int> primes = null)
        {
            var isPrime = new bool[max + 1];
            for (int i = 2; i < isPrime.Length; i++) isPrime[i] = true;
            for (int i = 2; i * i <= max; i++)
                if (!isPrime[i]) continue;
                else for (int j = i * i; j <= max; j += i) isPrime[j] = false;
            if (primes != null) for (int i = 0; i <= max; i++) if (isPrime[i]) primes.Add(i);

            return isPrime;
        }
    }
    #endregion
}

// https://bitbucket.org/camypaper/complib
namespace CompLib.Mathematics
{
    #region ModInt
    /// <summary>
    /// [0,<see cref="Mod"/>) までの値を取るような数
    /// </summary>
    public struct ModInt
    {
        /// <summary>
        /// 剰余を取る値．
        /// </summary>
        public const long Mod = (int)1e9 + 7;
        // public const long Mod = 998244353;

        /// <summary>
        /// 実際の数値．
        /// </summary>
        public long num;
        /// <summary>
        /// 値が <paramref name="n"/> であるようなインスタンスを構築します．
        /// </summary>
        /// <param name="n">インスタンスが持つ値</param>
        /// <remarks>パフォーマンスの問題上，コンストラクタ内では剰余を取りません．そのため，<paramref name="n"/> ∈ [0,<see cref="Mod"/>) を満たすような <paramref name="n"/> を渡してください．このコンストラクタは O(1) で実行されます．</remarks>
        public ModInt(long n) { num = n; }
        /// <summary>
        /// このインスタンスの数値を文字列に変換します．
        /// </summary>
        /// <returns>[0,<see cref="Mod"/>) の範囲内の整数を 10 進表記したもの．</returns>
        public override string ToString() { return num.ToString(); }
        public static ModInt operator +(ModInt l, ModInt r) { l.num += r.num; if (l.num >= Mod) l.num -= Mod; return l; }
        public static ModInt operator -(ModInt l, ModInt r) { l.num -= r.num; if (l.num < 0) l.num += Mod; return l; }
        public static ModInt operator *(ModInt l, ModInt r) { return new ModInt(l.num * r.num % Mod); }
        public static implicit operator ModInt(long n) { n %= Mod; if (n < 0) n += Mod; return new ModInt(n); }

        /// <summary>
        /// 与えられた 2 つの数値からべき剰余を計算します．
        /// </summary>
        /// <param name="v">べき乗の底</param>
        /// <param name="k">べき指数</param>
        /// <returns>繰り返し二乗法により O(N log N) で実行されます．</returns>
        public static ModInt Pow(ModInt v, long k) { return Pow(v.num, k); }

        /// <summary>
        /// 与えられた 2 つの数値からべき剰余を計算します．
        /// </summary>
        /// <param name="v">べき乗の底</param>
        /// <param name="k">べき指数</param>
        /// <returns>繰り返し二乗法により O(N log N) で実行されます．</returns>
        public static ModInt Pow(long v, long k)
        {
            long ret = 1;
            for (k %= Mod - 1; k > 0; k >>= 1, v = v * v % Mod)
                if ((k & 1) == 1) ret = ret * v % Mod;
            return new ModInt(ret);
        }
        /// <summary>
        /// 与えられた数の逆元を計算します．
        /// </summary>
        /// <param name="v">逆元を取る対象となる数</param>
        /// <returns>逆元となるような値</returns>
        /// <remarks>法が素数であることを仮定して，フェルマーの小定理に従って逆元を O(log N) で計算します．</remarks>
        public static ModInt Inverse(ModInt v) { return Pow(v, Mod - 2); }
    }
    #endregion
    #region Binomial Coefficient
    public class BinomialCoefficient
    {
        public ModInt[] fact, ifact;
        public BinomialCoefficient(int n)
        {
            fact = new ModInt[n + 1];
            ifact = new ModInt[n + 1];
            fact[0] = 1;
            for (int i = 1; i <= n; i++)
                fact[i] = fact[i - 1] * i;
            ifact[n] = ModInt.Inverse(fact[n]);
            for (int i = n - 1; i >= 0; i--)
                ifact[i] = ifact[i + 1] * (i + 1);
            ifact[0] = ifact[1];
        }
        public ModInt this[int n, int r]
        {
            get
            {
                if (n < 0 || n >= fact.Length || r < 0 || r > n) return 0;
                return fact[n] * ifact[n - r] * ifact[r];
            }
        }
        public ModInt RepeatedCombination(int n, int k)
        {
            if (k == 0) return 1;
            return this[n + k - 1, k];
        }
    }
    #endregion
}

namespace CompLib.Util
{
    using System;
    using System.Linq;

    class Scanner
    {
        private string[] _line;
        private int _index;
        private const char Separator = ' ';

        public Scanner()
        {
            _line = new string[0];
            _index = 0;
        }

        public string Next()
        {
            if (_index >= _line.Length)
            {
                string s;
                do
                {
                    s = Console.ReadLine();
                } while (s.Length == 0);

                _line = s.Split(Separator);
                _index = 0;
            }

            return _line[_index++];
        }

        public string ReadLine()
        {
            _index = _line.Length;
            return Console.ReadLine();
        }

        public int NextInt() => int.Parse(Next());
        public long NextLong() => long.Parse(Next());
        public double NextDouble() => double.Parse(Next());
        public decimal NextDecimal() => decimal.Parse(Next());
        public char NextChar() => Next()[0];
        public char[] NextCharArray() => Next().ToCharArray();

        public string[] Array()
        {
            string s = Console.ReadLine();
            _line = s.Length == 0 ? new string[0] : s.Split(Separator);
            _index = _line.Length;
            return _line;
        }

        public int[] IntArray() => Array().Select(int.Parse).ToArray();
        public long[] LongArray() => Array().Select(long.Parse).ToArray();
        public double[] DoubleArray() => Array().Select(double.Parse).ToArray();
        public decimal[] DecimalArray() => Array().Select(decimal.Parse).ToArray();
    }
}


using System;
using System.Globalization;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace Codeforces
{
    class Program : ProgramBase
    {
        private const long commonMod = 1000000007;

        static void Main(string[] args)
        {
            var p = new Program();
            var x = p.Solve();
            p.Out(x);
        }
        object Solve()
        {
            var n = ReadLong();
            var m = ReadLong();
            var k = ReadLong();
            if (k == -1 && Math.Abs(n - m) % 2 != 0)
                return 0;
            return fastpow(fastpow(2, n - 1), m - 1);
        }
        long fastpow(long b, long x)
        {
            checked
            {
                if (x == 0)
                    return 1;
                if (x == 1)
                    return b;
                if (x % 2 == 0)
                    return fastpow(b * b % commonMod, x / 2);
                return b * fastpow(b, x - 1) % commonMod;
            }
        }
        int nod(int a, int b)
        {
            if (a < b)
                return nod(b, a);
            if (b == 0)
                return a;
            return nod(b, a % b);
        }

        class End
        {
            public long Val { get; set; }
            public bool Left { get; set; }
        }
    }

    abstract class ProgramBase
    {
        bool? prod = null;
        StreamReader f;
        Queue<string> tokens;
        protected string FileName { private get; set; }

        protected string Read()
        {
            if (f == null)
                f = string.IsNullOrEmpty(FileName)
                    ? new StreamReader(Console.OpenStandardInput(1024 * 10), Encoding.ASCII, false, 1024 * 10)
                    : new StreamReader((GetProd() ? "" : "c:\\dev\\") + FileName);
            return f.ReadLine();
        }

        protected string ReadToken()
        {
            if (tokens == null || tokens.Count == 0)
                tokens = new Queue<string>(Read().Split(' '));
            return tokens.Dequeue();
        }

        protected long ReadLong() { return long.Parse(ReadToken()); }

        protected long[] ReadLongs()
        {
            var s = Read();
            if (s == "")
                return new long[0];
            //var i = s.IndexOf(' ');
            //return new[] { long.Parse(s.Substring(0, i)), long.Parse(s.Substring(i + 1)) };
            var tokens = s.Split(' ');
            var result = new long[tokens.Length];
            for (int i = 0; i < tokens.Length; i++)
                result[i] = long.Parse(tokens[i]);
            return result;
        }

        public void Out(object r)
        {
            if (string.IsNullOrEmpty(FileName))
                Console.WriteLine(r);
            else if (GetProd())
                File.WriteAllText(FileName, r.ToString());
            else
                Console.WriteLine(r);
        }

        private bool GetProd()
        {

            if (!prod.HasValue)
                try
                {
                    prod = Environment.MachineName != "RENADEEN-W7";
                }
                catch (Exception)
                {
                    prod = true;
                }
            return prod.Value;
        }
    }

    public static class Huj
    {
        public static T MinBy<T>(this IEnumerable<T> source, Func<T, double> func) where T : class
        {
            T result = null;
            var min = double.MaxValue;
            foreach (var item in source)
            {
                var current = func(item);
                if (min > current)
                {
                    min = current;
                    result = item;
                }
            }
            return result;
        }

        public static T MaxBy<T>(this IEnumerable<T> source, Func<T, double> func, T defaultValue = default(T))
        {
            T result = defaultValue;
            var max = double.MinValue;
            foreach (var item in source)
            {
                var current = func(item);
                if (max < current)
                {
                    max = current;
                    result = item;
                }
            }
            return result;
        }

        public static string JoinStrings(this IEnumerable<string> s, string d) { return string.Join(d, s.ToArray()); }

        public static string JoinStrings(this IEnumerable<int> s, string d) { return s.Select(x => x.ToString()).JoinStrings(d); }
        public static string JoinStrings(this IEnumerable<long> s, string d) { return s.Select(x => x.ToString()).JoinStrings(d); }
    }

}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApp1
{
    class Program
    {
        const int MAXN = 1000000007;
        static long QMul(long a, long b)
        {
            long res = 1;
            long tmp = a;

            while(b != 0)
            {
                if((b & 1L) == 1)
                {
                    res *= tmp;
                    res %= MAXN;
                }
                tmp *= tmp;
                tmp %= MAXN;
                b >>= 1;
            }

            return res;
        }

        static void Main(string[] args)
        {
            string[] input = Console.ReadLine().Split(' ');
            long[] arr = input.Select(x => Convert.ToInt64(x)).ToArray();

            long n = arr[0];
            long m = arr[1];
            long k = arr[2];

            if(k == -1 && (n+m) % 2 == 1)
            {
                Console.WriteLine("0");
            }
            else
            {
                Console.WriteLine(QMul(QMul(2, (m - 1)), (n - 1)).ToString());
            }
        }
    }
}


using CompLib.Util;
using System;
using System.Collections.Generic;

public class Program
{
    private int N, M, A, B;
    private int G0, X, Y, Z;

    public void Solve()
    {
        var sc = new Scanner();
        N = sc.NextInt();
        M = sc.NextInt();
        A = sc.NextInt();
        B = sc.NextInt();

        G0 = sc.NextInt();
        X = sc.NextInt();
        Y = sc.NextInt();
        Z = sc.NextInt();

        int[] H = new int[N * M];
        H[0] = G0;
        for (int i = 1; i < N * M; i++)
        {
            H[i] = (int) (((long) H[i - 1] * X + Y) % Z);
        }

        MinimumQueue[] q = new MinimumQueue[N];
        for (int i = 0; i < N; i++)
        {
            q[i] = new MinimumQueue();
            for (int j = 0; j < B - 1; j++)
            {
                q[i].Enqueue(H[i * M + j]);
            }
        }

        long ans = 0;
        for (int j = B - 1; j < M; j++)
        {
            var q2 = new MinimumQueue();
            for (int i = 0; i < N; i++)
            {
                q[i].Enqueue(H[i * M + j]);
                q2.Enqueue(q[i].Min());
                if (i >= A - 1)
                {
                    ans += q2.Min();
                    q2.Dequeue();
                }

                q[i].Dequeue();
            }
        }

        Console.WriteLine(ans);
    }

    public static void Main(string[] args) => new Program().Solve();
}

class MinimumStack
{
    private readonly Stack<(int num, int min)> stack;

    public MinimumStack()
    {
        stack = new Stack<(int num, int min)>();
    }

    public void Push(int num)
    {
        if (Count == 0) stack.Push((num, num));
        else stack.Push((num, Math.Min(num, stack.Peek().min)));
    }

    public int Peek()
    {
        return stack.Peek().num;
    }

    public int Pop()
    {
        return stack.Pop().num;
    }

    public int Min()
    {
        return Count == 0 ? int.MaxValue : stack.Peek().min;
    }

    public int Count => stack.Count;
}

class MinimumQueue
{
    private readonly MinimumStack s1, s2;

    public MinimumQueue()
    {
        s1 = new MinimumStack();
        s2 = new MinimumStack();
    }

    public void Enqueue(int l)
    {
        s2.Push(l);
    }

    private void Exec()
    {
        if (s1.Count == 0)
        {
            while (s2.Count > 0)
            {
                s1.Push(s2.Pop());
            }
        }
    }

    public int Peek()
    {
        Exec();
        return s1.Peek();
    }

    public int Dequeue()
    {
        Exec();
        return s1.Pop();
    }

    public int Min()
    {
        return Math.Min(s1.Min(), s2.Min());
    }

    public int Count => s1.Count + s2.Count;
}

namespace CompLib.Util
{
    using System;
    using System.Linq;

    class Scanner
    {
        private string[] _line;
        private int _index;
        private const char Separator = ' ';

        public Scanner()
        {
            _line = new string[0];
            _index = 0;
        }

        public string Next()
        {
            if (_index >= _line.Length)
            {
                string s;
                do
                {
                    s = Console.ReadLine();
                } while (s.Length == 0);

                _line = s.Split(Separator);
                _index = 0;
            }

            return _line[_index++];
        }

        public string ReadLine()
        {
            _index = _line.Length;
            return Console.ReadLine();
        }

        public int NextInt() => int.Parse(Next());
        public long NextLong() => long.Parse(Next());
        public double NextDouble() => double.Parse(Next());
        public decimal NextDecimal() => decimal.Parse(Next());
        public char NextChar() => Next()[0];
        public char[] NextCharArray() => Next().ToCharArray();

        public string[] Array()
        {
            string s = Console.ReadLine();
            _line = s.Length == 0 ? new string[0] : s.Split(Separator);
            _index = _line.Length;
            return _line;
        }

        public int[] IntArray() => Array().Select(int.Parse).ToArray();
        public long[] LongArray() => Array().Select(long.Parse).ToArray();
        public double[] DoubleArray() => Array().Select(double.Parse).ToArray();
        public decimal[] DecimalArray() => Array().Select(decimal.Parse).ToArray();
    }
}


using System;
using System.Numerics;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Linq;

class Solution
{
	class SlideMin
	{
		int i = 0;
		List<int> lst = new List<int>();
		public void Push(int x)
		{
			while (lst.Count > i && lst.Last() > x) lst.RemoveAt(lst.Count-1);
			lst.Add(x);
		}
		public void Pop(int x)
		{
			if (lst[i] == x) i++;
		}
		public int Top()
		{
			return lst[i];
		}
	};

	int n, m, a, b;
	int[,] M;

	void Make(int g, int x, int y, int z)
	{
		M = new int[n, m];
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < m; j++)
			{
				M[i, j] = g;
				g = (int)(((long)g * x + y) % z);
			}
		}
	}

	void Run()
	{
		var A = Array.ConvertAll(cin.ReadLine().Split(), int.Parse);
		n = A[0]; m = A[1]; a = A[2]; b = A[3];
		A = Array.ConvertAll(cin.ReadLine().Split(), int.Parse);
		Make(A[0], A[1], A[2], A[3]);

		int[,] MinRow = new int[n, m - b + 1];
		for (int i = 0; i < n; i++)
		{
			SlideMin slide = new SlideMin();
			for (int j = 0; j < b; j++)
			{
				slide.Push(M[i, j]);
			}
			for (int j = 0; j < m - b + 1; j++)
			{
				MinRow[i, j] = slide.Top();
				if (j == m - b) break;
				slide.Pop(M[i, j]);
				slide.Push(M[i, j + b]);
			}
		}

		long ans = 0;
		for (int j = 0; j < m - b + 1; j++)
		{
			SlideMin slide = new SlideMin();
			for (int i = 0; i < a; i++)
			{
				slide.Push(MinRow[i, j]);
			}
			for (int i = 0; i < n - a + 1; i++)
			{
				ans += slide.Top();
				if (i == n - a) break;
				slide.Pop(MinRow[i, j]);
				slide.Push(MinRow[i + a, j]);
			}
		}

		cout.Write(ans);
	}

	static TextReader cin;
	static TextWriter cout;

	static void Main()
	{
#if NARUT_LOCAL
		cin = new StreamReader("io/test.in", Encoding.ASCII);
#else
		cin = new StreamReader(Console.OpenStandardInput(), Encoding.ASCII);
#endif
		cout = new StreamWriter(Console.OpenStandardOutput(), Encoding.ASCII) { AutoFlush = false };
		(new Solution()).Run();
		cin.Close();
		cout.Close();
	}
}


/*
csc -debug E.cs && mono --debug E.exe <<< "3 4 2 1
1 2 3 59"
*/

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Reflection;

public struct QueueItem {
    public ulong Val;
    public int Index;
}

public class HelloWorld {
    public static void SolveCodeForces() {
        var n = cin.NextInt();
        var m = cin.NextInt();
        var a = cin.NextInt();
        var b = cin.NextInt();

        var Arr = Helpers.CreateArray(n, _ => new ulong[m]);
        {
            var g0 = cin.NextUlong();
            var x = cin.NextUlong();
            var y = cin.NextUlong();
            var z = cin.NextUlong();
            for (var i = 0; i < n; i++)
                for (var j = 0; j < m; j++) {
                    Arr[i][j] = g0;
                    g0 = (g0 * x + y) % z;
                }
        }

// System.Console.WriteLine("Arr:");
// foreach (var row in Arr)
//     System.Console.WriteLine(row.Join());

        var QVers = new Deque<QueueItem>[m];
        for (var j = 0; j < m; j++) {
            var Q = new Deque<QueueItem>();
            for (var i = 0; i < a; i++) {
                var x = Arr[i][j];
                AppendRight(Q, i, x);
            }
            QVers[j] = Q;
        }

        var ans = 0ul;

        for (var i = a - 1; i < n; i++) {
            var rowAns = 0ul;

            var Q = new Deque<QueueItem>();
            for (var j = 0; j < b; j++) {
                AppendRight(Q, j, QVers[j].Left.Val);
            }

            rowAns += Q.Left.Val;
            for (var j = b; j < m; j++) {
                Shift(Q, j - b);
                AppendRight(Q, j, QVers[j].Left.Val);
                rowAns += Q.Left.Val;
            }

            for (var j = 0; j < m; j++) {
                Shift(QVers[j], i - a + 1);
                if (i + 1 < n)
                    AppendRight(QVers[j], i + 1, Arr[i + 1][j]);
            }

// System.Console.WriteLine(new {i, rowAns});
            ans += rowAns;
        }
// System.Console.WriteLine(new {brute = SolveBrute(Arr, n, m, a, b)});

        System.Console.WriteLine(ans);
    }

    static ulong SolveBrute(ulong[][] Arr, int n, int m, int a, int b) {
        var ans = 0ul;

        for (var i = a-1; i < n; i++)
            for (var j = b-1; j < m; j++) {
                var min = Arr[i][j];
                for (var ii = 0; ii < a; ii++)
                    for (var jj = 0; jj < b; jj++)
                        min = Math.Min(min, Arr[i - ii][j - jj]);
                ans += min;
            }

        return ans;
    }

    static void AppendRight(Deque<QueueItem> Q, int i, ulong x) {
        while (Q.Count > 0 && Q.Right.Val >= x) Q.RemoveRight();
        Q.AppendRight(new QueueItem{ Val = x, Index = i });
    }

    static void Shift(Deque<QueueItem> Q, int i) {
        if (Q.Left.Index == i) Q.RemoveLeft();
    }

    static Scanner cin = new Scanner();
    static StringBuilder cout = new StringBuilder();

    static public void Main () {
        SolveCodeForces();
        // IncreaseStack(SolveCodeForces);
        // System.Console.Write(cout.ToString());
    }

    public static void IncreaseStack(ThreadStart action, int stackSize = 128000000)
    {
        var thread = new Thread(action, stackSize);
        thread.Start();
        thread.Join();
    }
}

public class Deque<T> : IEnumerable<T> {
    private T[] arr;
    private int index;
    private int count;
    private int n;

    public Deque(T[] arr) {
        this.arr = arr;
        n = arr.Length;
        count = arr.Length;
    }

    public Deque(int capacity = 8) {
        n = capacity;
        arr = new T[capacity];
    }

    public int Count => count;

    public T Left => this[0];
    public T Right => this[count - 1];

    public T this[int i] {
        get {
            if (i < 0 || i >= count) throw new InvalidOperationException(string.Format("Index {0} is out of range (count = {1})", i, count));
            return arr[(index + i) % n];
        }
    }

    public void AppendRight(T val) {
        EnsureSize();
        arr[(index + count) % n] = val;
        count++;
    }

    public void AppendLeft(T val) {
        EnsureSize();
        index = (index + n - 1) % n;
        arr[index] = val;
        count++;
    }

    public T RemoveLeft() {
        if (count == 0) throw new InvalidOperationException("Can't remove left because deque is empty");

        var result = arr[index];
        index = (index + 1) % n;
        count--;
        return result;
    }

    public T RemoveRight() {
        if (count == 0) throw new InvalidOperationException("Can't remove right because deque is empty");

        var result = arr[(index + count + n - 1) % n];
        count--;
        return result;
    }

    private void EnsureSize() {
        if (count == arr.Length) {
            var newArr = new T[arr.Length * 2];
            var left = Math.Min(count, arr.Length - index);
            Array.Copy(arr, index, newArr, 0, left);
            if (left < count)
                Array.Copy(arr, 0, newArr, left, count - left);
            arr = newArr;
            index = 0;
            n = newArr.Length;
        }
    }

    public IEnumerator<T> GetEnumerator()
    {
        for (var i = 0; i < count; i++) {
            yield return arr[(index + i) % n];
        }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

public static class Helpers {
    public static string Join<T>(this IEnumerable<T> arr) {
        return string.Join(" ", arr);
    }

    public static void Swap<T>(ref T a, ref T b) {
        var tmp = a;
        a = b;
        b = tmp;
    }

    public static T[] CreateArray<T>(int length, Func<int, T> itemCreate) {
        var result = new T[length];
        for (var i = 0; i < result.Length; i++)
            result[i] = itemCreate(i);
        return result;
    }
}

public class Scanner
{
    private string[] line = new string[0];
    private int index = 0;

    public string Next() {
        if (line.Length <= index) {
            line = Console.ReadLine().Split(' ');
            index = 0;
        }
        var res = line[index];
        index++;
        return res;
    }

    public int NextInt() {
        return int.Parse(Next());
    }

    public long NextLong() {
        return long.Parse(Next());
    }

    public ulong NextUlong() {
        return ulong.Parse(Next());
    }

    public string[] Array() {
        line = Console.ReadLine().Split(' ');
        index = line.Length;
        return line;
    }

    public int[] IntArray(int emptyPrefixLen = 0) {
        var array = Array();
        var result = new int[emptyPrefixLen + array.Length];
        for (int i = 0; i < array.Length; i++)
            result[emptyPrefixLen + i] = int.Parse(array[i]);
        return result;
    }

    public long[] LongArray() {
        var array = Array();
        var result = new long[array.Length];
        for (int i = 0; i < array.Length; i++)
            result[i] = long.Parse(array[i]);
        return result;
    }

    public ulong[] UlongArray() {
        var array = Array();
        var result = new ulong[array.Length];
        for (int i = 0; i < array.Length; i++)
            result[i] = ulong.Parse(array[i]);
        return result;
    }
}