//package ecr012;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

public class F3 {
	InputStream is;
	PrintWriter out;
	String INPUT = "";

	public static int[] sieveEratosthenes(int n) {
		if (n <= 32) {
			int[] primes = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31 };
			for (int i = 0; i < primes.length; i++) {
				if (n < primes[i]) {
					return Arrays.copyOf(primes, i);
				}
			}
			return primes;
		}

		int u = n + 32;
		double lu = Math.log(u);
		int[] ret = new int[(int) (u / lu + u / lu / lu * 1.5)];
		ret[0] = 2;
		int pos = 1;

		int[] isnp = new int[(n + 1) / 32 / 2 + 1];
		int sup = (n + 1) / 32 / 2 + 1;

		int[] tprimes = { 3, 5, 7, 11, 13, 17, 19, 23, 29, 31 };
		for (int tp : tprimes) {
			ret[pos++] = tp;
			int[] ptn = new int[tp];
			for (int i = (tp - 3) / 2; i < tp << 5; i += tp)
				ptn[i >> 5] |= 1 << (i & 31);
			for (int j = 0; j < sup; j += tp) {
				for (int i = 0; i < tp && i + j < sup; i++) {
					isnp[j + i] |= ptn[i];
				}
			}
		}

		// 3,5,7
		// 2x+3=n
		int[] magic = { 0, 1, 23, 2, 29, 24, 19, 3, 30, 27, 25, 11, 20, 8, 4, 13, 31, 22, 28, 18, 26, 10, 7, 12, 21, 17,
				9, 6, 16, 5, 15, 14 };
		int h = n / 2;
		for (int i = 0; i < sup; i++) {
			for (int j = ~isnp[i]; j != 0; j &= j - 1) {
				int pp = i << 5 | magic[(j & -j) * 0x076be629 >>> 27];
				int p = 2 * pp + 3;
				if (p > n)
					break;
				ret[pos++] = p;
				if ((long) p * p > n)
					continue;
				for (int q = (p * p - 3) / 2; q <= h; q += p)
					isnp[q >> 5] |= 1 << q;
			}
		}

		return Arrays.copyOf(ret, pos);
	}

	int[] primes = sieveEratosthenes(400000);

	void solve()
	{
		long n = nl();
		long ans = 0;
		MeisselLehmer2 ml = new MeisselLehmer2(n/2);
		for(int i = 0;i < primes.length;i++) {
			long plus = ml.pi(n/primes[i]) - (i+1);
			if(plus <= 0)break;
			ans += plus;
		}

		for(int p : primes) {
			if((long)p*p*p <= n) {
				ans++;
			}else {
				break;
			}
		}
		out.println(ans);
	}

	public static class MeisselLehmer2 {
		int[] primes;
//		int[] cump;
		int[] xcums;
		long[] isp;

		int cachelimit;
//		Map<Long, Long> picache;
//		Map<Long, Long> phicache;
		LongHashCounterL picache;
		LongHashCounterL phicache;
		boolean cachePhi = true;

		int[][] cumps;
//		int[] FP = {2,3,5,7,11,13,17};
		int[] FP = {2,3,5,7,11,13,17,19};
		int M = FP.length;

		int B = 100;
		// 10^14 -> 200
		// 10^14/8 -> 100~200

		public MeisselLehmer2(long n)
		{
			assert n >= 4;
//			picache = new HashMap<>();
//			phicache = new HashMap<>();
			picache = new LongHashCounterL();
			phicache = new LongHashCounterL();

			int s = (int)Math.sqrt(n)*B; // not overflow!
			cachelimit = s;
			this.primes = sieveEratosthenes(s);
			xcums = new int[(s>>>6)+1];
			isp = new long[(s>>>6)+1];
			for(int p : primes)isp[p>>>6] |= 1L<<p;
			for(int i = 0;i < xcums.length-1;i++)xcums[i+1] = xcums[i] + Long.bitCount(isp[i]);

			cumps = new int[M][];
			boolean[] b = {true};
			int len = 1;
			for(int i = 0;i < M;i++){
				len *= FP[i];
				boolean[] c = new boolean[len];
				for(int j = 0;j < FP[i];j++){
					System.arraycopy(b, 0, c, j*b.length, b.length);
				}
				for(int k = 0;k < len;k+=FP[i])c[k] = false;
				cumps[i] = new int[len+1];
				for(int j = 0;j < len;j++)cumps[i][j+1] = cumps[i][j] + (c[j] ? 1 : 0);
				FP[i] = len;
				b = c;
			}
		}

		private long sqrt(long n)
		{
			long i = Math.max(0, (long)Math.sqrt(n)-2);
			while(i*i <= n)i++;
			return i-1;
		}

		private long cbrt(long n)
		{
			long i = Math.max(0, (long)Math.cbrt(n)-2);
			while(i*i*i <= n)i++;
			return i-1;
		}

		public long pi(long x)
		{
			if(x <= cachelimit){
				int ix = (int)x;
				return xcums[ix>>>6] + Long.bitCount(isp[ix>>>6]<<~ix);
//				return cump[(int)x];
			}
			if(picache.containsKey(x))return picache.get(x);

			int A = (int)pi(sqrt(sqrt(x)));
			long ret = A + phi(x, A) - P2(x, A) - P3(x, A) - 1;
			picache.put(x, ret);
			return ret;
		}

		private long phi(long x, int A)
		{
			if(A > 0 && A-1 < M){
				return cumps[A-1][FP[A-1]] * (x/FP[A-1]) + cumps[A-1][(int)(x%FP[A-1]+1)];
			}
			if(A > 0 && x <= (long)primes[A-1]*primes[A-1]){
				return pi(x) - A + 1;
			}
			long code = x<<13|A;
			if(phicache.containsKey(code))return phicache.get(code);

			long ret = x;
			for(int i = A-1;i >= 0;i--)ret -= phi(x/primes[i], i);

			if(cachePhi)phicache.put(code, ret);
			return ret;
		}

		private long P2(long x, int A)
		{
			int B = (int)pi(sqrt(x));
			long ret = 0;
			for(int i = A;i < B;i++){
				ret += pi(x/primes[i]);
			}
			ret -= (long)(B-A)*(B+A-1)/2;
			return ret;
		}

		private long P3(long x, int A)
		{
			int C = (int)pi(cbrt(x));
			long ret = 0;
			for(int i = A;i < C;i++){
				long xi = x/primes[i];
				int B = (int)pi(sqrt(xi));
				for(int j = i;j < B;j++){
					ret += pi(xi/primes[j]) - j;
				}
			}
			return ret;
		}

		public static int[] sieveEratosthenes(int n) {
			if (n <= 32) {
				int[] primes = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31 };
				for (int i = 0; i < primes.length; i++) {
					if (n < primes[i]) {
						return Arrays.copyOf(primes, i);
					}
				}
				return primes;
			}

			int u = n + 32;
			double lu = Math.log(u);
			int[] ret = new int[(int) (u / lu + u / lu / lu * 1.5)];
			ret[0] = 2;
			int pos = 1;

			int[] isnp = new int[(n + 1) / 32 / 2 + 1];
			int sup = (n + 1) / 32 / 2 + 1;

			int[] tprimes = { 3, 5, 7, 11, 13, 17, 19, 23, 29, 31 };
			for (int tp : tprimes) {
				ret[pos++] = tp;
				int[] ptn = new int[tp];
				for (int i = (tp - 3) / 2; i < tp << 5; i += tp)
					ptn[i >> 5] |= 1 << (i & 31);
				for (int j = 0; j < sup; j += tp) {
					for (int i = 0; i < tp && i + j < sup; i++) {
						isnp[j + i] |= ptn[i];
					}
				}
			}

			// 3,5,7
			// 2x+3=n
			int[] magic = { 0, 1, 23, 2, 29, 24, 19, 3, 30, 27, 25, 11, 20, 8, 4, 13, 31, 22, 28, 18, 26, 10, 7, 12, 21, 17,
					9, 6, 16, 5, 15, 14 };
			int h = n / 2;
			for (int i = 0; i < sup; i++) {
				for (int j = ~isnp[i]; j != 0; j &= j - 1) {
					int pp = i << 5 | magic[(j & -j) * 0x076be629 >>> 27];
					int p = 2 * pp + 3;
					if (p > n)
						break;
					ret[pos++] = p;
					if ((long) p * p > n)
						continue;
					for (int q = (p * p - 3) / 2; q <= h; q += p)
						isnp[q >> 5] |= 1 << q;
				}
			}

			return Arrays.copyOf(ret, pos);
		}

		private static class LongHashCounterL {
			public long[] keys;
			public long[] allocated;
			private int scale = 1<<2;
			private int rscale = 1<<1;
			private int mask = scale-1;
			public int size = 0;

			public LongHashCounterL(){
				allocated = new long[scale];
				Arrays.fill(allocated, NG);
				keys = new long[scale];
			}

			// if value is NG, entry is removed. (e.g. 0)
			private static final int NG = 0;

			public boolean containsKey(long x)
			{
				int pos = h(x)&mask;
				while(allocated[pos] != NG){
					if(x == keys[pos])return true;
					pos = pos+1&mask;
				}
				return false;
			}

			public long get(long x)
			{
				int pos = h(x)&mask;
				while(allocated[pos] != NG){
					if(x == keys[pos])return allocated[pos];
					pos = pos+1&mask;
				}
				return NG;
			}

			public long put(long x, long v)
			{
				int pos = h(x)&mask;
				while(allocated[pos] != NG){
					if(x == keys[pos]){
						long oldval = allocated[pos];
						allocated[pos] = v;
						return oldval;
					}
					pos = pos+1&mask;
				}
				if(size == rscale){
					resizeAndPut(x, v);
				}else{
					keys[pos] = x;
					allocated[pos] = v;
				}
				size++;
				return 0;
			}

			public long inc(long x, long v)
			{
				int pos = h(x)&mask;
				while(allocated[pos] != NG){
					if(x == keys[pos]){
						allocated[pos] += v;
						return allocated[pos];
					}
					pos = pos+1&mask;
				}
				if(size == rscale){
					resizeAndPut(x, v);
				}else{
					keys[pos] = x;
					allocated[pos] = v;
				}
				size++;
				return v;
			}

			public boolean remove(long x)
			{
				int pos = h(x)&mask;
				while(allocated[pos] != NG){
					if(x == keys[pos]){
						size--;
						// take last and fill rmpos
						int last = pos;
						pos = pos+1&mask;
						while(allocated[pos] != NG){
							int lh = h(keys[pos])&mask;
							// lh <= last < pos
							if(
									lh <= last && last < pos ||
									pos < lh && lh <= last ||
									last < pos && pos < lh
									){
								keys[last] = keys[pos];
								allocated[last] = allocated[pos];
								last = pos;
							}
							pos = pos+1&mask;
						}
						keys[last] = 0;
						allocated[last] = NG;

						return true;
					}
					pos = pos+1&mask;
				}
				return false;
			}

			private void resizeAndPut(long x, long v)
			{
				int nscale = scale<<1;
				int nrscale = rscale<<1;
				int nmask = nscale-1;
				long[] nallocated = new long[nscale];
				Arrays.fill(nallocated, NG);
				long[] nkeys = new long[nscale];
				for(int i = next(0);i < scale;i = next(i+1)){
					long y = keys[i];
					int pos = h(y)&nmask;
					while(nallocated[pos] != NG)pos = pos+1&nmask;
					nkeys[pos] = y;
					nallocated[pos] = allocated[i];
				}
				{
					int pos = h(x)&nmask;
					while(nallocated[pos] != NG)pos = pos+1&nmask;
					nkeys[pos] = x;
					nallocated[pos] = v;
				}
				allocated = nallocated;
				keys = nkeys;
				scale = nscale;
				rscale = nrscale;
				mask = nmask;
			}

			public int next(int itr)
			{
				while(itr < scale && allocated[itr] == NG)itr++;
				return itr;
			}

			private int h(long x)
			{
				x ^= x>>>33;
				x *= 0xff51afd7ed558ccdL;
				x ^= x>>>33;
				x *= 0xc4ceb9fe1a85ec53L;
				x ^= x>>>33;
				return (int)x;
			}

			@Override
			public String toString()
			{
				StringBuilder sb = new StringBuilder();
				for(int i = next(0);i < scale;i = next(i+1)){
					sb.append(",");
					sb.append(keys[i] + ":" + allocated[i]);
				}
				return sb.length() == 0 ? "" : sb.substring(1);
			}
		}
	}

	void run() throws Exception
	{
		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		tr(System.currentTimeMillis()-s+"ms");
	}

	public static void main(String[] args) throws Exception { new F3().run(); }

	private byte[] inbuf = new byte[1024];
	public int lenbuf = 0, ptrbuf = 0;

	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf){
			ptrbuf = 0;
			try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
	private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

	private double nd() { return Double.parseDouble(ns()); }
	private char nc() { return (char)skip(); }

	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b))){
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private char[][] nm(int n, int m)
	{
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}

	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}

	private int ni()
	{
		int num = 0, b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}


//package ecr012;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

public class F3 {
	InputStream is;
	PrintWriter out;
	String INPUT = "100000000000";

	public static int[] sieveEratosthenes(int n) {
		if (n <= 32) {
			int[] primes = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31 };
			for (int i = 0; i < primes.length; i++) {
				if (n < primes[i]) {
					return Arrays.copyOf(primes, i);
				}
			}
			return primes;
		}

		int u = n + 32;
		double lu = Math.log(u);
		int[] ret = new int[(int) (u / lu + u / lu / lu * 1.5)];
		ret[0] = 2;
		int pos = 1;

		int[] isnp = new int[(n + 1) / 32 / 2 + 1];
		int sup = (n + 1) / 32 / 2 + 1;

		int[] tprimes = { 3, 5, 7, 11, 13, 17, 19, 23, 29, 31 };
		for (int tp : tprimes) {
			ret[pos++] = tp;
			int[] ptn = new int[tp];
			for (int i = (tp - 3) / 2; i < tp << 5; i += tp)
				ptn[i >> 5] |= 1 << (i & 31);
			for (int j = 0; j < sup; j += tp) {
				for (int i = 0; i < tp && i + j < sup; i++) {
					isnp[j + i] |= ptn[i];
				}
			}
		}

		// 3,5,7
		// 2x+3=n
		int[] magic = { 0, 1, 23, 2, 29, 24, 19, 3, 30, 27, 25, 11, 20, 8, 4, 13, 31, 22, 28, 18, 26, 10, 7, 12, 21, 17,
				9, 6, 16, 5, 15, 14 };
		int h = n / 2;
		for (int i = 0; i < sup; i++) {
			for (int j = ~isnp[i]; j != 0; j &= j - 1) {
				int pp = i << 5 | magic[(j & -j) * 0x076be629 >>> 27];
				int p = 2 * pp + 3;
				if (p > n)
					break;
				ret[pos++] = p;
				if ((long) p * p > n)
					continue;
				for (int q = (p * p - 3) / 2; q <= h; q += p)
					isnp[q >> 5] |= 1 << q;
			}
		}

		return Arrays.copyOf(ret, pos);
	}

	int[] primes = sieveEratosthenes(400000);

	void solve()
	{
		long n = nl();
		long ans = 0;
		MeisselLehmer2 ml = new MeisselLehmer2(n/2);
		for(int i = 0;i < primes.length;i++) {
			long plus = ml.pi(n/primes[i]) - (i+1);
			if(plus <= 0)break;
			ans += plus;
		}

		for(int p : primes) {
			if((long)p*p*p <= n) {
				ans++;
			}else {
				break;
			}
		}
		out.println(ans);
	}

	public static class MeisselLehmer2 {
		int[] primes;
//		int[] cump;
		int[] xcums;
		long[] isp;

		int cachelimit;
//		Map<Long, Long> picache;
//		Map<Long, Long> phicache;
		LongHashCounterL picache;
		LongHashCounterL phicache;
		boolean cachePhi = false;

		int[][] cumps;
//		int[] FP = {2,3,5,7,11,13,17};
		int[] FP = {2,3,5,7,11,13,17,19};
		int M = FP.length;

		int B = 100;
		// 10^14 -> 200
		// 10^14/8 -> 100~200

		public MeisselLehmer2(long n)
		{
			assert n >= 4;
//			picache = new HashMap<>();
//			phicache = new HashMap<>();
			picache = new LongHashCounterL();
			phicache = new LongHashCounterL();

			int s = (int)Math.sqrt(n)*B; // not overflow!
			cachelimit = s;
			this.primes = sieveEratosthenes(s);
			xcums = new int[(s>>>6)+1];
			isp = new long[(s>>>6)+1];
			for(int p : primes)isp[p>>>6] |= 1L<<p;
			for(int i = 0;i < xcums.length-1;i++)xcums[i+1] = xcums[i] + Long.bitCount(isp[i]);

			cumps = new int[M][];
			boolean[] b = {true};
			int len = 1;
			for(int i = 0;i < M;i++){
				len *= FP[i];
				boolean[] c = new boolean[len];
				for(int j = 0;j < FP[i];j++){
					System.arraycopy(b, 0, c, j*b.length, b.length);
				}
				for(int k = 0;k < len;k+=FP[i])c[k] = false;
				cumps[i] = new int[len+1];
				for(int j = 0;j < len;j++)cumps[i][j+1] = cumps[i][j] + (c[j] ? 1 : 0);
				FP[i] = len;
				b = c;
			}
		}

		private long sqrt(long n)
		{
			long i = Math.max(0, (long)Math.sqrt(n)-2);
			while(i*i <= n)i++;
			return i-1;
		}

		private long cbrt(long n)
		{
			long i = Math.max(0, (long)Math.cbrt(n)-2);
			while(i*i*i <= n)i++;
			return i-1;
		}

		public long pi(long x)
		{
			if(x <= cachelimit){
				int ix = (int)x;
				return xcums[ix>>>6] + Long.bitCount(isp[ix>>>6]<<~ix);
//				return cump[(int)x];
			}
			if(picache.containsKey(x))return picache.get(x);

			int A = (int)pi(sqrt(sqrt(x)));
			long ret = A + phi(x, A) - P2(x, A) - P3(x, A) - 1;
			picache.put(x, ret);
			return ret;
		}

		private long phi(long x, int A)
		{
			if(A > 0 && A-1 < M){
				return cumps[A-1][FP[A-1]] * (x/FP[A-1]) + cumps[A-1][(int)(x%FP[A-1]+1)];
			}
			if(A > 0 && x <= (long)primes[A-1]*primes[A-1]){
				return pi(x) - A + 1;
			}
//			long code = x<<13|A;
//			if(phicache.containsKey(code))return phicache.get(code);

			long ret = x;
			for(int i = A-1;i >= 0;i--)ret -= phi(x/primes[i], i);

//			if(cachePhi)phicache.put(code, ret);
			return ret;
		}

		private long P2(long x, int A)
		{
			int B = (int)pi(sqrt(x));
			long ret = 0;
			for(int i = A;i < B;i++){
				ret += pi(x/primes[i]);
			}
			ret -= (long)(B-A)*(B+A-1)/2;
			return ret;
		}

		private long P3(long x, int A)
		{
			int C = (int)pi(cbrt(x));
			long ret = 0;
			for(int i = A;i < C;i++){
				long xi = x/primes[i];
				int B = (int)pi(sqrt(xi));
				for(int j = i;j < B;j++){
					ret += pi(xi/primes[j]) - j;
				}
			}
			return ret;
		}

		public static int[] sieveEratosthenes(int n) {
			if (n <= 32) {
				int[] primes = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31 };
				for (int i = 0; i < primes.length; i++) {
					if (n < primes[i]) {
						return Arrays.copyOf(primes, i);
					}
				}
				return primes;
			}

			int u = n + 32;
			double lu = Math.log(u);
			int[] ret = new int[(int) (u / lu + u / lu / lu * 1.5)];
			ret[0] = 2;
			int pos = 1;

			int[] isnp = new int[(n + 1) / 32 / 2 + 1];
			int sup = (n + 1) / 32 / 2 + 1;

			int[] tprimes = { 3, 5, 7, 11, 13, 17, 19, 23, 29, 31 };
			for (int tp : tprimes) {
				ret[pos++] = tp;
				int[] ptn = new int[tp];
				for (int i = (tp - 3) / 2; i < tp << 5; i += tp)
					ptn[i >> 5] |= 1 << (i & 31);
				for (int j = 0; j < sup; j += tp) {
					for (int i = 0; i < tp && i + j < sup; i++) {
						isnp[j + i] |= ptn[i];
					}
				}
			}

			// 3,5,7
			// 2x+3=n
			int[] magic = { 0, 1, 23, 2, 29, 24, 19, 3, 30, 27, 25, 11, 20, 8, 4, 13, 31, 22, 28, 18, 26, 10, 7, 12, 21, 17,
					9, 6, 16, 5, 15, 14 };
			int h = n / 2;
			for (int i = 0; i < sup; i++) {
				for (int j = ~isnp[i]; j != 0; j &= j - 1) {
					int pp = i << 5 | magic[(j & -j) * 0x076be629 >>> 27];
					int p = 2 * pp + 3;
					if (p > n)
						break;
					ret[pos++] = p;
					if ((long) p * p > n)
						continue;
					for (int q = (p * p - 3) / 2; q <= h; q += p)
						isnp[q >> 5] |= 1 << q;
				}
			}

			return Arrays.copyOf(ret, pos);
		}

		private static class LongHashCounterL {
			public long[] keys;
			public long[] allocated;
			private int scale = 1<<2;
			private int rscale = 1<<1;
			private int mask = scale-1;
			public int size = 0;

			public LongHashCounterL(){
				allocated = new long[scale];
				Arrays.fill(allocated, NG);
				keys = new long[scale];
			}

			// if value is NG, entry is removed. (e.g. 0)
			private static final int NG = 0;

			public boolean containsKey(long x)
			{
				int pos = h(x)&mask;
				while(allocated[pos] != NG){
					if(x == keys[pos])return true;
					pos = pos+1&mask;
				}
				return false;
			}

			public long get(long x)
			{
				int pos = h(x)&mask;
				while(allocated[pos] != NG){
					if(x == keys[pos])return allocated[pos];
					pos = pos+1&mask;
				}
				return NG;
			}

			public long put(long x, long v)
			{
				int pos = h(x)&mask;
				while(allocated[pos] != NG){
					if(x == keys[pos]){
						long oldval = allocated[pos];
						allocated[pos] = v;
						return oldval;
					}
					pos = pos+1&mask;
				}
				if(size == rscale){
					resizeAndPut(x, v);
				}else{
					keys[pos] = x;
					allocated[pos] = v;
				}
				size++;
				return 0;
			}

			public long inc(long x, long v)
			{
				int pos = h(x)&mask;
				while(allocated[pos] != NG){
					if(x == keys[pos]){
						allocated[pos] += v;
						return allocated[pos];
					}
					pos = pos+1&mask;
				}
				if(size == rscale){
					resizeAndPut(x, v);
				}else{
					keys[pos] = x;
					allocated[pos] = v;
				}
				size++;
				return v;
			}

			public boolean remove(long x)
			{
				int pos = h(x)&mask;
				while(allocated[pos] != NG){
					if(x == keys[pos]){
						size--;
						// take last and fill rmpos
						int last = pos;
						pos = pos+1&mask;
						while(allocated[pos] != NG){
							int lh = h(keys[pos])&mask;
							// lh <= last < pos
							if(
									lh <= last && last < pos ||
									pos < lh && lh <= last ||
									last < pos && pos < lh
									){
								keys[last] = keys[pos];
								allocated[last] = allocated[pos];
								last = pos;
							}
							pos = pos+1&mask;
						}
						keys[last] = 0;
						allocated[last] = NG;

						return true;
					}
					pos = pos+1&mask;
				}
				return false;
			}

			private void resizeAndPut(long x, long v)
			{
				int nscale = scale<<1;
				int nrscale = rscale<<1;
				int nmask = nscale-1;
				long[] nallocated = new long[nscale];
				Arrays.fill(nallocated, NG);
				long[] nkeys = new long[nscale];
				for(int i = next(0);i < scale;i = next(i+1)){
					long y = keys[i];
					int pos = h(y)&nmask;
					while(nallocated[pos] != NG)pos = pos+1&nmask;
					nkeys[pos] = y;
					nallocated[pos] = allocated[i];
				}
				{
					int pos = h(x)&nmask;
					while(nallocated[pos] != NG)pos = pos+1&nmask;
					nkeys[pos] = x;
					nallocated[pos] = v;
				}
				allocated = nallocated;
				keys = nkeys;
				scale = nscale;
				rscale = nrscale;
				mask = nmask;
			}

			public int next(int itr)
			{
				while(itr < scale && allocated[itr] == NG)itr++;
				return itr;
			}

			private int h(long x)
			{
				x ^= x>>>33;
				x *= 0xff51afd7ed558ccdL;
				x ^= x>>>33;
				x *= 0xc4ceb9fe1a85ec53L;
				x ^= x>>>33;
				return (int)x;
			}

			@Override
			public String toString()
			{
				StringBuilder sb = new StringBuilder();
				for(int i = next(0);i < scale;i = next(i+1)){
					sb.append(",");
					sb.append(keys[i] + ":" + allocated[i]);
				}
				return sb.length() == 0 ? "" : sb.substring(1);
			}
		}
	}

	void run() throws Exception
	{
		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		tr(System.currentTimeMillis()-s+"ms");
	}

	public static void main(String[] args) throws Exception { new F3().run(); }

	private byte[] inbuf = new byte[1024];
	public int lenbuf = 0, ptrbuf = 0;

	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf){
			ptrbuf = 0;
			try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
	private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

	private double nd() { return Double.parseDouble(ns()); }
	private char nc() { return (char)skip(); }

	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b))){
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private char[][] nm(int n, int m)
	{
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}

	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}

	private int ni()
	{
		int num = 0, b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}


import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		new Main().run();
	}

	public void run() {
		Scanner sc = new Scanner(System.in);
		long n = sc.nextLong();
		System.out.println(f(n));
	}

	long f(long n) {
		int Len = (int) 4e5;
		long[] pi_upper = new long[Len];
		long[] pi_lower = new long[Len];
		for (int i = 1; i < Len; ++i) {
			pi_lower[i] = i;
			pi_upper[i] = n / i;
		}
		boolean[] isPrime = new boolean[Len];
		Arrays.fill(isPrime, true);
		isPrime[0] = false;
		isPrime[1] = false;

		ArrayList<Integer> primeList = new ArrayList<>();
		for (int i = 2; i < isPrime.length; ++i) {
			if (!isPrime[i]) {
				continue;
			}
			primeList.add(i);
			for (int j = i * 2; j < isPrime.length; j += i) {
				isPrime[j] = false;
			}
		}
		for (int t = 0; t < primeList.size(); ++t) {
			int p = primeList.get(t);
			for (int i = 1; i < Len && n / i >= (long) p * p; ++i) {
				pi_upper[i] -= ((long) p * i < Len ? pi_upper[p * i] : pi_lower[(int) (n / i / p)]) - (t + 1);
			}
			for (int i = Len - 1; i >= (long) p * p; --i) {
				pi_lower[i] -= pi_lower[i / p] - (t + 1);
			}
		}
		long ans = 0;
		for (long p : primeList) {
			if (p * p > n) {
				break;
			}
			if (p * p * p <= n && p * p * p > 0) {
				++ans;
			}
			if (n / p > p) {
				if (p < Len)
					ans += pi_upper[(int) p] - pi_lower[(int) p];
				else
					ans += pi_lower[(int) (n / p)] - pi_lower[(int) p];
			}
		}
		return ans;
	}

	void tr(Object... objects) {
		System.out.println(Arrays.deepToString(objects));
	}
}


//package prac;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

public class ECR66G {
	InputStream is;
	PrintWriter out;
	String INPUT = "";

	int[][] st;

	/*
[[0, 163, 1496, 2466, 3288, 4930, 5916, 6902, 7888]]
[[0, 163, 911, 1807, 2629, 4107, 5093, 6079, 7020]]
[[0, 163, 911, 1733, 2046, 3615, 4469, 5587, 6197]]
[[0, 163, 911, 1733, 1972, 3032, 3977, 5004, 5705]]
[[0, 163, 911, 1733, 1972, 2958, 3394, 4930, 5122]]	 *
	 */
	void solve()
	{
		int n = ni(), K = ni();
		int[] a = na(n);
		int[] ra = new int[n];
		for(int i = 0;i < n;i++)ra[i] = -a[i];
		st = build(ra);

		long[] dp = new long[n+1];
		Arrays.fill(dp, Long.MAX_VALUE / 2);
		dp[0] = 0;
		for(int i = 1;i <= K;i++) {
			dp = go(dp);
		}
		out.println(dp[n]);
	}

	long[] go(long[] dp)
	{
		int n = dp.length-1;
		long[] ret = new long[n+1];
		int[] is = new int[n+1];
		int[] hs = new int[n+1];
		int sp = 0;
		for(int i = 1;i <= n;i++) {
			while(sp > 0 && -hs[sp-1] < i)sp--;
			if(sp == 0 || f(is[sp-1], i, dp) > f(i-1, i, dp)) {
				while(sp > 0 && f(is[sp-1], -hs[sp-1], dp) > f(i-1, -hs[sp-1], dp)) {
					sp--;
				}
				if(sp > 0) {
					int low = i, high = -hs[sp-1]+1;
					while(high - low > 1) {
						int x = high+low>>1;
						if(f(is[sp-1], x, dp) > f(i-1, x, dp)) {
							low = x;
						}else {
							high = x;
						}
					}
					is[sp] = i-1;
					hs[sp] = -low;
					sp++;
				}else {
					is[sp] = i-1;
					hs[sp] = -n;
					sp++;
				}
			}
//			if(i == 7) {
//				tr(Arrays.copyOf(is, sp), Arrays.copyOf(hs, sp), f(is[1], 7, dp), f(i-1, 7, dp));
//			}

			int ind = lowerBound(hs, 0, sp, -i+1)-1;
			ret[i] = f(is[ind], i, dp);
		}
		return ret;
	}

	long f(int l, int r, long[] dp)
	{
		return dp[l] - (long)rmq(st, l, r) * (r-l);
	}

	public static int lowerBound(int[] a, int v){ return lowerBound(a, 0, a.length, v); }
	public static int lowerBound(int[] a, int l, int r, int v)
	{
		if(l > r || l < 0 || r > a.length)throw new IllegalArgumentException();
		int low = l-1, high = r;
		while(high-low > 1){
			int h = high+low>>>1;
			if(a[h] >= v){
				high = h;
			}else{
				low = h;
			}
		}
		return high;
	}

	public static int[][] build(int[] a)
	{
		int n = a.length;
		int b = 32-Integer.numberOfLeadingZeros(n);
		int[][] ret = new int[b][];
		for(int i = 0, l = 1;i < b;i++, l*=2) {
			if(i == 0) {
				ret[i] = a;
			}else {
				ret[i] = new int[n-l+1];
				for(int j = 0;j < n-l+1;j++) {
					ret[i][j] = Math.min(ret[i-1][j], ret[i-1][j+l/2]);
				}
			}
		}
		return ret;
	}

	// [a,b)
	public static int rmq(int[][] or, int l, int r)
	{
//		assert l <= r;
		if(l >= r)return Integer.MAX_VALUE;
		// 1:0, 2:1, 3:1, 4:2, 5:2, 6:2, 7:2, 8:3
		int t = 31-Integer.numberOfLeadingZeros(r-l);
		return Math.min(or[t][l], or[t][r-(1<<t)]);
	}

	void run() throws Exception
	{
		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		tr(System.currentTimeMillis()-s+"ms");
	}

	public static void main(String[] args) throws Exception { new ECR66G().run(); }

	private byte[] inbuf = new byte[1024];
	public int lenbuf = 0, ptrbuf = 0;

	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf){
			ptrbuf = 0;
			try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
	private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

	private double nd() { return Double.parseDouble(ns()); }
	private char nc() { return (char)skip(); }

	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b))){
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private char[][] nm(int n, int m)
	{
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}

	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}

	private int ni()
	{
		int num = 0, b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}


//package prac;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

public class ECR66G {
	InputStream is;
	PrintWriter out;
	String INPUT = "";

	int[][] st;

	void solve()
	{
		int n = ni(), K = ni();
		int[] a = na(n);
		int[] ra = new int[n];
		for(int i = 0;i < n;i++)ra[i] = -a[i];
		st = build(ra);

		long[] dp = new long[n+1];
		Arrays.fill(dp, Long.MAX_VALUE / 2);
		dp[0] = 0;
		for(int i = 1;i <= K;i++) {
			dp = go(dp);
		}
		out.println(dp[n]);
	}

	long[] go(long[] dp)
	{
		int n = dp.length-1;
		long[] ret = new long[n+1];
		int[] is = new int[n+1];
		int[] hs = new int[n+1];
		int sp = 0;
		for(int i = 1;i <= n;i++) {
			if(sp == 0 || f(is[sp-1], i, dp) > f(i-1, i, dp)) {
				while(sp > 0 && f(is[sp-1], hs[sp-1], dp) > f(i-1, hs[sp-1], dp)) {
					sp--;
				}
				if(sp > 0) {
					int low = i-1, high = n+1;
					while(high - low > 1) {
						int x = high+low>>1;
						if(f(is[sp-1], x, dp) > f(i-1, x, dp)) {
							low = x;
						}else {
							high = x;
						}
					}
					is[sp] = i-1;
					hs[sp] = low;
					sp++;
				}else {
					is[sp] = i-1;
					hs[sp] = i-1;
					sp++;
				}
			}

			int ind = lowerBound(hs, 0, sp, i-1);
			ret[i] = f(is[ind], i, dp);
		}
		return ret;
	}

	long f(int l, int r, long[] dp)
	{
		return dp[l] - (long)rmq(st, l, r) * (r-l);
	}

	public static int lowerBound(int[] a, int v){ return lowerBound(a, 0, a.length, v); }
	public static int lowerBound(int[] a, int l, int r, int v)
	{
		if(l > r || l < 0 || r > a.length)throw new IllegalArgumentException();
		int low = l-1, high = r;
		while(high-low > 1){
			int h = high+low>>>1;
			if(a[h] >= v){
				high = h;
			}else{
				low = h;
			}
		}
		return high;
	}

	public static int[][] build(int[] a)
	{
		int n = a.length;
		int b = 32-Integer.numberOfLeadingZeros(n);
		int[][] ret = new int[b][];
		for(int i = 0, l = 1;i < b;i++, l*=2) {
			if(i == 0) {
				ret[i] = a;
			}else {
				ret[i] = new int[n-l+1];
				for(int j = 0;j < n-l+1;j++) {
					ret[i][j] = Math.min(ret[i-1][j], ret[i-1][j+l/2]);
				}
			}
		}
		return ret;
	}

	// [a,b)
	public static int rmq(int[][] or, int l, int r)
	{
//		assert l <= r;
		if(l >= r)return Integer.MAX_VALUE;
		// 1:0, 2:1, 3:1, 4:2, 5:2, 6:2, 7:2, 8:3
		int t = 31-Integer.numberOfLeadingZeros(r-l);
		return Math.min(or[t][l], or[t][r-(1<<t)]);
	}

	void run() throws Exception
	{
		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		tr(System.currentTimeMillis()-s+"ms");
	}

	public static void main(String[] args) throws Exception { new ECR66G().run(); }

	private byte[] inbuf = new byte[1024];
	public int lenbuf = 0, ptrbuf = 0;

	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf){
			ptrbuf = 0;
			try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
	private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

	private double nd() { return Double.parseDouble(ns()); }
	private char nc() { return (char)skip(); }

	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b))){
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private char[][] nm(int n, int m)
	{
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}

	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}

	private int ni()
	{
		int num = 0, b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}


 import java.io.*;
import java.util.*;

public class methodOne {

	static final int P = 1_000_000_007;

	void submit() {
		int n = nextInt();
		int m = nextInt();
		long exp = nextLong();
		int[] a = new int[n];
		int[] b = new int[m];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		int maxCoef = 0;
		for (int i = 0; i < m; i++) {
			b[i] = nextInt();
			maxCoef = Math.max(maxCoef, b[i]);
		}

		int[] bPoly = new int[maxCoef + 1];
		bPoly[maxCoef] = 1;
		for (int pow : b) {
			bPoly[maxCoef - pow]--;
			if (bPoly[maxCoef - pow] < 0) {
				bPoly[maxCoef - pow] += P;
			}
		}

		int[] aPoly = {};
		for (int pow : a) {
			aPoly = sum(aPoly, quotPow(new int[] { 0, 1 }, bPoly, pow));
		}
		int[] ans = quotPow(aPoly, bPoly, exp);

		ans = prod(ans, quotPow(new int[] { 0, 1 }, bPoly, maxCoef));
		ans = quot(ans, bPoly);

		out.println((long)ans[0] * inv(P - bPoly[0]) % P);
	}

	int inv(int x) {
		return x == 1 ? 1 : P - (int)((long)(P / x) * inv(P % x) % P);
	}

	int[] quotPow(int[] a, int[] b, long n) {
		a = quot(a, b);
		int[] ret = { 1 };
		for (; n > 0; n >>= 1) {
			if ((n & 1) == 1) {
				ret = quot(prod(ret, a), b);
			}
			a = quot(prod(a, a), b);
		}
		return ret;
	}

	int[] sum(int[] a, int[] b) {
		int[] c = Arrays.copyOf(a, Math.max(a.length, b.length));
		for (int i = 0; i < b.length; i++) {
			c[i] += b[i];
			if (c[i] >= P) {
				c[i] -= P;
			}
		}
		return c;
	}

	int[] prod(int[] a, int[] b) {
		int[] c = new int[a.length + b.length - 1];
		for (int i = 0; i < a.length; i++) {
			for (int j = 0; j < b.length; j++) {
				c[i + j] += (int) ((long) a[i] * b[j] % P);
				if (c[i + j] >= P) {
					c[i + j] -= P;
				}
			}
		}
		return c;
	}

	int[] quot(int[] a, int[] b) {
		a = a.clone();
		// leading coef of b is 1
		if (a.length < b.length) {
			return a;
		}
		int degB = b.length - 1;
		for (int ptr = a.length - 1; ptr >= degB; ptr--) {
			long coef = a[ptr];
			for (int i = 0, j = ptr - degB; i < degB; i++, j++) {
				a[j] -= (int) (coef * b[i] % P);
				if (a[j] < 0) {
					a[j] += P;
				}
			}
		}
		return Arrays.copyOf(a, degB);
	}

	void preCalc() {

	}

	void stress() {

	}

	void test() {

	}

	public static void methodOne() throws IOException {
		br = new BufferedReader(new InputStreamReader(System.in));
		out = new PrintWriter(System.out);
		preCalc();
		submit();
		out.close();
	}

	static final Random rng = new Random();

	static int rand(int l, int r) {
		return l + rng.nextInt(r - l + 1);
	}

	BufferedReader br;
	PrintWriter out;
	StringTokenizer st;

	String nextToken() {
		while (st == null || !st.hasMoreTokens()) {
			try {
				st = new StringTokenizer(br.readLine());
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
		return st.nextToken();
	}

	String nextString() {
		try {
			return br.readLine();
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	int nextInt() {
		return Integer.parseInt(nextToken());
	}

	long nextLong() {
		return Long.parseLong(nextToken());
	}

	double nextDouble() {
		return Double.parseDouble(nextToken());
	}

	public static void main(String[] args) throws IOException {
		new methodOne();
	}
}


import java.util.*;

public class methodOne{
	public static void flowersAndChocolate() {
		Scanner s=new Scanner(System.in);
		int n=s.nextInt();
		int k=s.nextInt();
		if(k%2==0 || k>=2*n){
			System.out.println("-1");
		}
		else{
			if(n==1){
				System.out.println("1");
			}
			else{
				int []array=new int[n];
				merge(0,n,k,array,1);
				System.out.print(array[0]);
				for (int i =1; i <n; i++) {
					System.out.print(" "+array[i]);
				}

			}
		}
	}

	public static void merge(int start,int end,int k,int[]a,int num){
		if(k==1){
			for (int i =start; i <end; i++) {
				a[i]=num;
				num++;
			}
		}
		else{
			if(k>1 && start<end){
				k--;
				int temp1=k/2;
				int temp2=k-temp1;
				if(temp1%2==0){
					temp1--;
					temp2++;
				}
				int middle=(start+end)/2;
				merge(middle,end,temp2,a,num);
				merge(start,middle,temp1,a,num+end-middle);
			}
		}
	}
public static void main(){
	flowersAndChocolate();
	merge();
}

}


import java.io.*;
import java.util.*;

public class G {

	static final int P = 1_000_000_007;

	void submit() {
		int n = nextInt();
		int m = nextInt();
		long exp = nextLong();
		int[] a = new int[n];
		int[] b = new int[m];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		int maxCoef = 0;
		for (int i = 0; i < m; i++) {
			b[i] = nextInt();
			maxCoef = Math.max(maxCoef, b[i]);
		}

		int[] bPoly = new int[maxCoef + 1];
		bPoly[maxCoef] = 1;
		for (int pow : b) {
			bPoly[maxCoef - pow]--;
			if (bPoly[maxCoef - pow] < 0) {
				bPoly[maxCoef - pow] += P;
			}
		}

		int[] aPoly = {};
		for (int pow : a) {
			aPoly = sum(aPoly, quotPow(new int[] { 0, 1 }, bPoly, pow));
		}
		int[] ans = quotPow(aPoly, bPoly, exp);

		ans = prod(ans, quotPow(new int[] { 0, 1 }, bPoly, maxCoef));
		ans = quot(ans, bPoly);

		out.println((long)ans[0] * inv(P - bPoly[0]) % P);
	}

	int inv(int x) {
		return x == 1 ? 1 : P - (int)((long)(P / x) * inv(P % x) % P);
	}

	int[] quotPow(int[] a, int[] b, long n) {
		a = quot(a, b);
		int[] ret = { 1 };
		for (; n > 0; n >>= 1) {
			if ((n & 1) == 1) {
				ret = quot(prod(ret, a), b);
			}
			a = quot(prod(a, a), b);
		}
		return ret;
	}

	int[] sum(int[] a, int[] b) {
		int[] c = Arrays.copyOf(a, Math.max(a.length, b.length));
		for (int i = 0; i < b.length; i++) {
			c[i] += b[i];
			if (c[i] >= P) {
				c[i] -= P;
			}
		}
		return c;
	}

	int[] prod(int[] a, int[] b) {
		int[] c = new int[a.length + b.length - 1];
		for (int i = 0; i < a.length; i++) {
			for (int j = 0; j < b.length; j++) {
				c[i + j] += (int) ((long) a[i] * b[j] % P);
				if (c[i + j] >= P) {
					c[i + j] -= P;
				}
			}
		}
		return c;
	}

	int[] quot(int[] a, int[] b) {
		a = a.clone();
		// leading coef of b is 1
		if (a.length < b.length) {
			return a;
		}
		int degB = b.length - 1;
		for (int ptr = a.length - 1; ptr >= degB; ptr--) {
			long coef = a[ptr];
			for (int i = 0, j = ptr - degB; i < degB; i++, j++) {
				a[j] -= (int) (coef * b[i] % P);
				if (a[j] < 0) {
					a[j] += P;
				}
			}
		}
		return Arrays.copyOf(a, degB);
	}

	void preCalc() {

	}

	void stress() {

	}

	void test() {

	}

	G() throws IOException {
		br = new BufferedReader(new InputStreamReader(System.in));
		out = new PrintWriter(System.out);
		preCalc();
		submit();
		// stress();
		// test();
		out.close();
	}

	static final Random rng = new Random();

	static int rand(int l, int r) {
		return l + rng.nextInt(r - l + 1);
	}

	public static void main(String[] args) throws IOException {
		new G();
	}

	BufferedReader br;
	PrintWriter out;
	StringTokenizer st;

	String nextToken() {
		while (st == null || !st.hasMoreTokens()) {
			try {
				st = new StringTokenizer(br.readLine());
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
		return st.nextToken();
	}

	String nextString() {
		try {
			return br.readLine();
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	int nextInt() {
		return Integer.parseInt(nextToken());
	}

	long nextLong() {
		return Long.parseLong(nextToken());
	}

	double nextDouble() {
		return Double.parseDouble(nextToken());
	}
}


import java.util.*;

public class methodOne{
	public static void flowersAndChocolate() {
		Scanner s=new Scanner(System.in);
		int n=s.nextInt();
		int k=s.nextInt();
		if(k%2==0 || k>=2*n){
			System.out.println("-1");
		}
		else{
			if(n==1){
				System.out.println("1");
			}
			else{
				int []array=new int[n];
				merge(0,n,k,array,1);
				System.out.print(array[0]);
				for (int i =1; i <n; i++) {
					System.out.print(" "+array[i]);
				}

			}
		}
	}

	public static void merge(int start,int end,int k,int[]a,int num){
		if(k==1){
			for (int i =start; i <end; i++) {
				a[i]=num;
				num++;
			}
		}
		else{
			if(k>1 && start<end){
				k--;
				int temp1=k/2;
				int temp2=k-temp1;
				if(temp1%2==0){
					temp1--;
					temp2++;
				}
				int middle=(start+end)/2;
				merge(middle,end,temp2,a,num);
				merge(start,middle,temp1,a,num+end-middle);
			}
		}
	}
public static void main(){
	flowersAndChocolate();
}

}


import java.io.*;
import java.util.*;

public class E890 {

	long mod = 1000000000L+7L;
	long[] fac;
	long[] f;

	private void solve() throws Exception {
		int n = nextInt();
		int k = nextInt();
		if(k > n) {
			out.println(0);
			return;
		}
		fac = new long[n+1];
		fac[0] = 1;
		for(int i = 1; i <= n; i++) fac[i] = (fac[i-1]*i)%mod;
		f = new long[n+1];
		for(int i = 0; i <= k; i++) f[i] = fac[i];
		for(int i = k; i < n; i++) f[i+1] = (((i+1)*f[i])%mod - ((fac[i] * f[i-k])%mod * inverse(fac[i-k]))%mod + mod)%mod;
		long res = 0;
		for(int i = 0; i < n; i++) res = (res+(f[n-i-1]*((fac[n-1]*inverse(fac[n-1-i]))%mod))%mod)%mod;
		out.println((fac[n]-res+mod)%mod);
	}

	long inverse(long n) {
        long i = mod, v = 0, d = 1;
        while (n>0) {
            long t = i/n, x = n;
            n = i % x;
            i = x;
            x = d;
            d = v - t*x;
            v = x;
        }
        v %= mod;
        return (v+mod)%mod;
    }

	public static void main(String[] args) {
		new E890().run();
	}

	private BufferedReader in;
	private PrintWriter out;
	private StringTokenizer tokenizer;

	public void run() {
		try {
			in = new BufferedReader(new InputStreamReader(System.in));
			tokenizer = null;
			out = new PrintWriter(System.out);
			solve();
			in.close();
			out.close();
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		}
	}

	private int nextInt() throws IOException {
		return Integer.parseInt(nextToken());
	}

	private long nextLong() throws IOException {
		return Long.parseLong(nextToken());
	}

	private float nextFloat() throws IOException {
		return Float.parseFloat(nextToken());
	}

	private String nextLine() throws IOException {
		return new String(in.readLine());
	}

	private String nextToken() throws IOException {
		while (tokenizer == null || !tokenizer.hasMoreTokens()) {
			tokenizer = new StringTokenizer(in.readLine());
		}
		return tokenizer.nextToken();
	}

}


import java.io.*;
import java.util.*;

/**
 *
 * @author True
 */

public class Main {
    public static final int N = 1000001;
    public static final int M = 1000000007;
    public static int[] inv = new int[N];
    public static int[] dp = new int[N];
    public static int[] ch = new int[N];
    public static void main(String args[]) {
        Scanner in;
        PrintStream out;
        try{
            in = new Scanner(new FileInputStream("java.in"));
            out = new PrintStream("java.out");
        } catch (FileNotFoundException e) {
            in = new Scanner (new BufferedInputStream(System.in));
            out = System.out;
        }
        for(int i=0; i<N; i++) {
            if(i<2) {
                inv[i] = i;
                ch[i] = 1;
            }
            else {
                inv[i] = (int) ((long) (M / i) * (M - inv[M%i]) % M);
                ch[i] = (int) ((long) ch[i-1] * i % M);
            }
        }
        int n = in.nextInt();
        int k = in.nextInt();
        dp[0] = 1;
        for(int i=1; i<=n; i++) {
            if(i<=k) dp[i] = 1;
            else dp[i] = (int)((long) (dp[i-1] - dp[i-k-1] + M) * inv[i] % M);
            dp[i] = (dp[i-1] + dp[i]) % M;
        }
        out.println((ch[n] - (long) dp[n-1] * ch[n-1] % M + M) % M);
    }
}


import java.util.*;
import java.io.*;
import java.lang.*;
import java.math.*;
public class C {
    public static int mod = 1000000007;
    public static void main(String[] args) throws Exception {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
        // int n = Integer.parseInt(bf.readLine());
        StringTokenizer st = new StringTokenizer(bf.readLine());
        // int[] a = new int[n]; for(int i=0; i<n; i++) a[i] = Integer.parseInt(st.nextToken());
        int n = Integer.parseInt(st.nextToken());
        int k = Integer.parseInt(st.nextToken());
        if(k>=n) k = n-1;
        long[] g = new long[n+1];
        for(int i=1; i<=k; i++) g[i] = 1;
        long sum = k;
        for(int i=k+1; i<=n; i++) {
          g[i] = sum * inv(i) % mod;
          sum += g[i];
          sum -= g[i-k];
          sum += mod;
          sum %= mod;
        }
        long[] nm = new long[n+1];
        nm[0] = 1;
        long[] fact = new long[n+1];
        fact[0] = 1;
        for(int i=1; i<=n; i++) {
          fact[i] = fact[i-1] * i % mod;
        }
        for(int i=1; i<=n; i++) {
          nm[i] = g[i] * fact[i] % mod;
        }
        //out.println(Arrays.toString(nm));
        long ans = 0;
        for(int i=0; i<n; i++) ans += nm[i] * inv((int)fact[i]) % mod;
        ans %= mod;
        ans *= fact[n-1];
        ans %= mod;
        ans = fact[n] - ans;
        ans += mod;
        ans %= mod;
        out.println(ans);
        out.close(); System.exit(0);
    }
    public static int exp(int base, int e) {
      if(e == 0) return 1;
      if(e == 1) return base;
      int val = exp(base, e/2);
      int ans = (int)(1L*val*val % mod);
      if(e % 2 == 1)
        ans = (int)(1L*ans*base % mod);
      return ans;
    }
    public static int inv(int base) {
      return exp(base, mod-2);
    }
}


import java.util.*;
import java.io.*;
import java.lang.*;
import java.math.*;
public class C {
    public static int mod = 1000000007;
    public static void main(String[] args) throws Exception {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
        // int n = Integer.parseInt(bf.readLine());
        StringTokenizer st = new StringTokenizer(bf.readLine());
        // int[] a = new int[n]; for(int i=0; i<n; i++) a[i] = Integer.parseInt(st.nextToken());
        int n = Integer.parseInt(st.nextToken());
        int k = Integer.parseInt(st.nextToken());
        long[] g = new long[n+1];
        for(int i=1; i<=k; i++) g[i] = 1;
        long sum = k;
        for(int i=k+1; i<=n; i++) {
          g[i] = sum * inv(i) % mod;
          sum += g[i];
          sum -= g[i-k];
          sum += mod;
          sum %= mod;
        }
        long[] nm = new long[n+1];
        nm[0] = 1;
        long[] fact = new long[n+1];
        fact[0] = 1;
        for(int i=1; i<=n; i++) {
          fact[i] = fact[i-1] * i % mod;
        }
        for(int i=1; i<=n; i++) {
          nm[i] = g[i] * fact[i] % mod;
        }
        //out.println(Arrays.toString(nm));
        long ans = 0;
        for(int i=0; i<n; i++) ans += nm[i] * inv((int)fact[i]) % mod;
        ans %= mod;
        ans *= fact[n-1];
        ans %= mod;
        ans = fact[n] - ans;
        ans += mod;
        ans %= mod;
        out.println(ans);
        out.close(); System.exit(0);
    }
    public static int exp(int base, int e) {
      if(e == 0) return 1;
      if(e == 1) return base;
      int val = exp(base, e/2);
      int ans = (int)(1L*val*val % mod);
      if(e % 2 == 1)
        ans = (int)(1L*ans*base % mod);
      return ans;
    }
    public static int inv(int base) {
      return exp(base, mod-2);
    }
}


import java.io.*;
import java.util.*;

public class CF1156G {
	static class V {
		String s;
		char op;
		V u, v;
		int d;
		V(String s) {
			this.s = s;
		}
		V(char op, V u, V v) {
			this.op = op; this.u = u; this.v = v;
			d = Math.max(u.d, v.d) + 1;
		}
		@Override
		public String toString() {
			return s + "=" + u.s + op + v.s;
		}
	}
	static ArrayList<V> list = new ArrayList<>();
	static HashSet<String> set = new HashSet<>();
	static Random rand = new Random();
	static String getX() {
		String s;
		do {
			char x = (char) ('a' + rand.nextInt(26));
			s = "" + x + rand.nextInt(1000);
		} while (set.contains(s));
		return s;
	}
	static void dfs(V w, String s) {
		if (w.d == 0)
			return;
		if (w.s == null) {
			w.s = s;
			list.add(w);
			dfs(w.u, getX());
			dfs(w.v, getX());
		}
	}
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int n = Integer.parseInt(br.readLine());
		HashMap<String, V> mp = new HashMap<>();
		while (n-- > 0) {
			char[] cc = br.readLine().toCharArray();
			int m = cc.length;
			int p = -1, q = -1;
			for (int j = 0; j < m; j++)
				if (cc[j] == '=')
					p = j;
				else if (cc[j] == '$' || cc[j] == '^' || cc[j] == '#' || cc[j] == '&')
					q = j;
			String lvalue = new String(cc, 0, p);
			set.add(lvalue);
			if (q == -1) {
				String rvalue = new String(cc, p + 1, m - p - 1);
				set.add(rvalue);
				V v = mp.get(rvalue);
				if (v == null) {
					v = new V(rvalue);
					mp.put(rvalue, v);
				}
				mp.put(lvalue, v);
			} else {
				String arg1 = new String(cc, p + 1, q - p - 1);
				String arg2 = new String(cc, q + 1, m - q - 1);
				set.add(arg1);
				set.add(arg2);
				char op = cc[q];
				V u = mp.get(arg1);
				if (u == null) {
					u = new V(arg1);
					mp.put(arg1, u);
				}
				V v = mp.get(arg2);
				if (v == null) {
					v = new V(arg2);
					mp.put(arg2, v);
				}
				V w = new V(op, u, v);
				mp.put(lvalue, w);
			}
		}
		V w = mp.get("res");
		if (w == null) {
			System.out.println(0);
			return;
		}
		dfs(w, "res");
		Collections.sort(list, (u, v) -> u.d - v.d);
		PrintWriter pw = new PrintWriter(System.out);
		pw.println(list.size());
		for (V v : list)
			pw.println(v);
		pw.close();
	}
}


import java.io.*;
import java.util.*;

public class CF1156G {
	static class V {
		String s;
		char op = ' ';
		V u, v;
		int d;
		V(String s) {
			this.s = s;
		}
		V(char op, V u, V v) {
			this.op = op; this.u = u; this.v = v;
			d = Math.max(u.d, v.d) + 1;
		}
		@Override
		public String toString() {
			return s + "=" + u.s + op + v.s;
		}
	}
	static ArrayList<V> list = new ArrayList<>();
	static HashSet<String> set = new HashSet<>();
	static Random rand = new Random();
	static String getX() {
		String s;
		do {
			char x = (char) ('a' + rand.nextInt(26));
			s = "" + x + rand.nextInt(1000);
		} while (set.contains(s));
		return s;
	}
	static void dfs(V w, String s) {
		if (w.d == 0)
			return;
		if (w.s == null) {
			w.s = s;
			list.add(w);
			dfs(w.u, getX());
			dfs(w.v, getX());
		}
	}
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int n = Integer.parseInt(br.readLine());
		HashMap<String, V> mp = new HashMap<>();
		while (n-- > 0) {
			char[] cc = br.readLine().toCharArray();
			int m = cc.length;
			int p = -1, q = -1;
			for (int j = 0; j < m; j++)
				if (cc[j] == '=')
					p = j;
				else if (cc[j] == '$' || cc[j] == '^' || cc[j] == '#' || cc[j] == '&')
					q = j;
			String lvalue = new String(cc, 0, p);
			set.add(lvalue);
			if (q == -1) {
				String rvalue = new String(cc, p + 1, m - p - 1);
				set.add(rvalue);
				V v = mp.get(rvalue);
				if (v == null) {
					v = new V(rvalue);
					mp.put(rvalue, v);
				}
				mp.put(lvalue, v);
			} else {
				String arg1 = new String(cc, p + 1, q - p - 1);
				String arg2 = new String(cc, q + 1, m - q - 1);
				set.add(arg1);
				set.add(arg2);
				char op = cc[q];
				V u = mp.get(arg1);
				if (u == null) {
					u = new V(arg1);
					mp.put(arg1, u);
				}
				V v = mp.get(arg2);
				if (v == null) {
					v = new V(arg2);
					mp.put(arg2, v);
				}
				V w = new V(op, u, v);
				mp.put(lvalue, w);
			}
		}
		V w = mp.get("res");
		if (w == null) {
			System.out.println(0);
			return;
		}
		if (w.op == ' ') {
			if (w.s.equals("res")) {
				System.out.println(0);
			} else {
				System.out.println(1);
				System.out.println("res=" + w.s);
			}
			return;
		}
		dfs(w, "res");
		Collections.sort(list, (u, v) -> u.d - v.d);
		PrintWriter pw = new PrintWriter(System.out);
		pw.println(list.size());
		for (V v : list)
			pw.println(v);
		pw.close();
	}
}


import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.*;
import java.util.regex.Pattern;

public class CF1156G {
    public static void main(String[] args) throws Exception {
        boolean local = System.getProperty("ONLINE_JUDGE") == null;
        boolean async = false;

        Charset charset = Charset.forName("ascii");

        FastIO io = local ? new FastIO(new FileInputStream("D:\\DATABASE\\TESTCASE\\Code.in"), System.out, charset) : new FastIO(System.in, System.out, charset);
        Task task = new Task(io, new Debug(local));

        if (async) {
            Thread t = new Thread(null, task, "dalt", 1 << 27);
            t.setPriority(Thread.MAX_PRIORITY);
            t.start();
            t.join();
        } else {
            task.run();
        }

        if (local) {
            io.cache.append("\n\n--memory -- \n" + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) >> 20) + "M");
        }

        io.flush();
    }

    public static class Task implements Runnable {
        final FastIO io;
        final Debug debug;
        int inf = (int) 1e8;
        int mod = (int) 1e9 + 7;

        public int mod(int val) {
            val %= mod;
            if (val < 0) {
                val += mod;
            }
            return val;
        }

        public int mod(long val) {
            val %= mod;
            if (val < 0) {
                val += mod;
            }
            return (int) val;
        }

        public Task(FastIO io, Debug debug) {
            this.io = io;
            this.debug = debug;
        }

        @Override
        public void run() {
            solve();
        }

        Map<String, Var> context = new HashMap<>();
        HashSet<String> remainNames = new HashSet<>();
        Deque<String> useable = new ArrayDeque<>();

        public void solve() {
            int n = io.readInt();

            for (int i = 0; i < n; i++) {
                parseLine();
            }

            StringBuilder builder = new StringBuilder();
            for (int i = 'a'; i <= 'z'; i++) {
                for (int i2 = 'a'; i2 <= 'z'; i2++) {
                    for (int i3 = 'a'; i3 <= 'z'; i3++) {
                        for (int i4 = 'a'; i4 <= 'z'; i4++) {
                            builder.setLength(0);
                            builder.append((char) i).append((char) i2).append((char) i3).append((char) i4);
                            remainNames.add(builder.toString());
                        }
                    }
                }
            }

            remainNames.removeAll(context.keySet());
            useable.addAll(remainNames);

            String finalName = rebuild(getVar("res"));
            if (trace.isEmpty() && !finalName.equals("res")) {
                trace.add("res=" + finalName);
                finalName = "res";
            }
            if (!trace.isEmpty()) {
                trace.add(trace.remove(trace.size() - 1).replace(finalName, "res"));
            }
            io.cache.append(trace.size()).append('\n');
            for (String s : trace) {
                io.cache.append(s).append('\n');
            }
        }

        List<String> trace = new ArrayList<>();

        Random random = new Random(12345678);
        Map<String, String> exprToName = new HashMap<>();

        public String randomName() {
            return useable.removeFirst();
        }

        public String register(String expr, String name) {
            if (exprToName.containsKey(expr)) {
                return exprToName.get(expr);
            } else {
                trace.add(name + "=" + expr);
                exprToName.put(expr, name);
                return name;
            }
        }

        StringBuilder common = new StringBuilder(1024);

        public String concat(String... parts) {
            common.setLength(0);
            for (String part : parts) {
                common.append(part);
            }
            return common.toString();
        }

        Map<Var, String> cache = new IdentityHashMap<>();

        public String rebuild(Var var) {
            if (cache.containsKey(var)) {
                return cache.get(var);
            }
            String retName = null;
            if (var instanceof UnknownVar) {
                retName = ((UnknownVar) var).name;
            }
            if (var instanceof Reference) {
                retName = rebuild(var.arg1);
            }
            if (var instanceof Expr) {
                String name = randomName();
                String arg1 = rebuild(var.arg1);
                String arg2 = rebuild(((Expr) var).arg2);
                retName = register(concat(arg1, ((Expr) var).op, arg2), name);
            }
            cache.put(var, retName);
            return retName;
        }

        char[] line = new char[100];
        Lexer lexer = new Lexer();

        public Var getVar(String s) {
            if (!context.containsKey(s)) {
                UnknownVar var = new UnknownVar();
                var.name = s;
                context.put(s, var);
            }
            return context.get(s);
        }

        public void parseLine() {
            int len = io.readString(line, 0);
            lexer.reset(line, len);
            String variable = lexer.readName();
            lexer.readOp();
            String arg1 = lexer.readName();
            if (!lexer.hasMore()) {
                Reference reference = new Reference();
                reference.arg1 = getVar(arg1);
                context.put(variable, reference);
            } else {
                Expr expr = new Expr();
                expr.arg1 = getVar(arg1);
                expr.op = lexer.readOp();
                expr.arg2 = getVar(lexer.readName());
                Reference reference = new Reference();
                reference.arg1 = expr;
                context.put(variable, reference);
            }
        }
    }

    public static class Lexer {
        char[] data;
        int len;
        int rpos = 0;
        StringBuilder builder = new StringBuilder();

        public void reset(char[] data, int len) {
            this.data = data;
            this.len = len;
            rpos = 0;
        }

        public boolean hasMore() {
            return rpos != len;
        }

        public String readName() {
            builder.setLength(0);
            while (rpos < len && data[rpos] != '=' &&
                    data[rpos] != '$' && data[rpos] != '^' && data[rpos] != '#' && data[rpos] != '&') {
                builder.append(data[rpos++]);
            }
            return builder.toString();
        }

        public String readOp() {
            builder.setLength(0);
            builder.append(data[rpos++]);
            return builder.toString();
        }
    }

    public static class Var {
        Var arg1;
    }

    public static class Expr extends Var {
        String op;
        Var arg2;
    }

    public static class UnknownVar extends Var {
        String name;
    }

    public static class Reference extends Var {

    }

    public static class FastIO {
        public final StringBuilder cache = new StringBuilder();
        private final InputStream is;
        private final OutputStream os;
        private final Charset charset;
        private StringBuilder defaultStringBuf = new StringBuilder(1 << 8);
        private byte[] buf = new byte[1 << 13];
        private int bufLen;
        private int bufOffset;
        private int next;

        public FastIO(InputStream is, OutputStream os, Charset charset) {
            this.is = is;
            this.os = os;
            this.charset = charset;
        }

        public FastIO(InputStream is, OutputStream os) {
            this(is, os, Charset.forName("ascii"));
        }

        private int read() {
            while (bufLen == bufOffset) {
                bufOffset = 0;
                try {
                    bufLen = is.read(buf);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                if (bufLen == -1) {
                    return -1;
                }
            }
            return buf[bufOffset++];
        }

        public void skipBlank() {
            while (next >= 0 && next <= 32) {
                next = read();
            }
        }

        public int readInt() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            int val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

        public long readLong() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            long val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

        public double readDouble() {
            boolean sign = true;
            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+';
                next = read();
            }

            long val = 0;
            while (next >= '0' && next <= '9') {
                val = val * 10 + next - '0';
                next = read();
            }
            if (next != '.') {
                return sign ? val : -val;
            }
            next = read();
            long radix = 1;
            long point = 0;
            while (next >= '0' && next <= '9') {
                point = point * 10 + next - '0';
                radix = radix * 10;
                next = read();
            }
            double result = val + (double) point / radix;
            return sign ? result : -result;
        }

        public String readString(StringBuilder builder) {
            skipBlank();

            while (next > 32) {
                builder.append((char) next);
                next = read();
            }

            return builder.toString();
        }

        public String readString() {
            defaultStringBuf.setLength(0);
            return readString(defaultStringBuf);
        }

        public int readLine(char[] data, int offset) {
            int originalOffset = offset;
            while (next != -1 && next != '\n') {
                data[offset++] = (char) next;
                next = read();
            }
            return offset - originalOffset;
        }

        public int readString(char[] data, int offset) {
            skipBlank();

            int originalOffset = offset;
            while (next > 32) {
                data[offset++] = (char) next;
                next = read();
            }

            return offset - originalOffset;
        }

        public int readString(byte[] data, int offset) {
            skipBlank();

            int originalOffset = offset;
            while (next > 32) {
                data[offset++] = (byte) next;
                next = read();
            }

            return offset - originalOffset;
        }

        public char readChar() {
            skipBlank();
            char c = (char) next;
            next = read();
            return c;
        }

        public void flush() {
            try {
                os.write(cache.toString().getBytes(charset));
                os.flush();
                cache.setLength(0);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        public boolean hasMore() {
            skipBlank();
            return next != -1;
        }
    }

    public static class Debug {
        private boolean allowDebug;

        public Debug(boolean allowDebug) {
            this.allowDebug = allowDebug;
        }

        public void assertTrue(boolean flag) {
            if (!allowDebug) {
                return;
            }
            if (!flag) {
                fail();
            }
        }

        public void fail() {
            throw new RuntimeException();
        }

        public void assertFalse(boolean flag) {
            if (!allowDebug) {
                return;
            }
            if (flag) {
                fail();
            }
        }

        private void outputName(String name) {
            System.out.print(name + " = ");
        }

        public void debug(String name, int x) {
            if (!allowDebug) {
                return;
            }

            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, long x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, double x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, int[] x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.toString(x));
        }

        public void debug(String name, long[] x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.toString(x));
        }

        public void debug(String name, double[] x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.toString(x));
        }

        public void debug(String name, Object x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, Object... x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.deepToString(x));
        }
    }
}


//package round722;
import java.io.*;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.InputMismatchException;
import java.util.Queue;

public class E {
	InputStream is;
	FastWriter out;
	String INPUT = "4";

	void solve()
	{
		final int mod = 998244353;
		int n = ni();
		if(n == 1){
			out.println(5);
			return;
		}
		long[] f = new long[n+1];
		long[] g = new long[n+1];
		f[0] = 1;
		f[1] = 2;
		g[1] = 1;
		long i2 = invl(2, mod);
		for(int i = 2;i <= n;i++){
			g[i] = (((f[i-1]+1)*f[i-1]%mod*i2%mod - (f[i-2]+1)*f[i-2]%mod*i2%mod ) % mod + mod) % mod;
			f[i] = f[i-1] + g[i];
			f[i] %= mod;
		}

		long an = 0;
		for(int i = 1;i <= n-1;i++){
			an += (g[i+1] - g[i] + mod) * (g[n-i-1+1]-1);
			an %= mod;
		}

		long b0 = f[n-1];
		long b1 = f[n];
		b1 %= mod;
		long ans =
			b1*(b1+1)%mod*(b1+2)%mod*invl(6, mod) % mod -
			b0*(b0+1)%mod*(b0+2)%mod*invl(6, mod) % mod;
		ans = ans * 2 - 1 + an;
		ans %= mod;
		if(ans < 0)ans += mod;
		out.println(ans);
	}

	public static long invl(long a, long mod) {
		long b = mod;
		long p = 1, q = 0;
		while (b > 0) {
			long c = a / b;
			long d;
			d = a;
			a = b;
			b = d % b;
			d = p;
			p = q;
			q = d - c * q;
		}
		return p < 0 ? p + mod : p;
	}

	public static long pow(long a, long n, long mod) {
		//		a %= mod;
		long ret = 1;
		int x = 63 - Long.numberOfLeadingZeros(n);
		for (; x >= 0; x--) {
			ret = ret * ret % mod;
			if (n << 63 - x < 0) ret = ret * a % mod;
		}
		return ret;
	}

	void run() throws Exception
	{
		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new FastWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		tr(System.currentTimeMillis()-s+"ms");
	}

	public static void main(String[] args) throws Exception { new E().run(); }

	private byte[] inbuf = new byte[1024];
	public int lenbuf = 0, ptrbuf = 0;

	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf){
			ptrbuf = 0;
			try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
	private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

	private double nd() { return Double.parseDouble(ns()); }
	private char nc() { return (char)skip(); }

	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b))){
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}

	private long[] nal(int n)
	{
		long[] a = new long[n];
		for(int i = 0;i < n;i++)a[i] = nl();
		return a;
	}

	private char[][] nm(int n, int m) {
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}

	private int[][] nmi(int n, int m) {
		int[][] map = new int[n][];
		for(int i = 0;i < n;i++)map[i] = na(m);
		return map;
	}

	private int ni() { return (int)nl(); }

	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	public static class FastWriter
	{
		private static final int BUF_SIZE = 1<<13;
		private final byte[] buf = new byte[BUF_SIZE];
		private final OutputStream out;
		private int ptr = 0;

		private FastWriter(){out = null;}

		public FastWriter(OutputStream os)
		{
			this.out = os;
		}

		public FastWriter(String path)
		{
			try {
				this.out = new FileOutputStream(path);
			} catch (FileNotFoundException e) {
				throw new RuntimeException("FastWriter");
			}
		}

		public FastWriter write(byte b)
		{
			buf[ptr++] = b;
			if(ptr == BUF_SIZE)innerflush();
			return this;
		}

		public FastWriter write(char c)
		{
			return write((byte)c);
		}

		public FastWriter write(char[] s)
		{
			for(char c : s){
				buf[ptr++] = (byte)c;
				if(ptr == BUF_SIZE)innerflush();
			}
			return this;
		}

		public FastWriter write(String s)
		{
			s.chars().forEach(c -> {
				buf[ptr++] = (byte)c;
				if(ptr == BUF_SIZE)innerflush();
			});
			return this;
		}

		private static int countDigits(int l) {
			if (l >= 1000000000) return 10;
			if (l >= 100000000) return 9;
			if (l >= 10000000) return 8;
			if (l >= 1000000) return 7;
			if (l >= 100000) return 6;
			if (l >= 10000) return 5;
			if (l >= 1000) return 4;
			if (l >= 100) return 3;
			if (l >= 10) return 2;
			return 1;
		}

		public FastWriter write(int x)
		{
			if(x == Integer.MIN_VALUE){
				return write((long)x);
			}
			if(ptr + 12 >= BUF_SIZE)innerflush();
			if(x < 0){
				write((byte)'-');
				x = -x;
			}
			int d = countDigits(x);
			for(int i = ptr + d - 1;i >= ptr;i--){
				buf[i] = (byte)('0'+x%10);
				x /= 10;
			}
			ptr += d;
			return this;
		}

		private static int countDigits(long l) {
			if (l >= 1000000000000000000L) return 19;
			if (l >= 100000000000000000L) return 18;
			if (l >= 10000000000000000L) return 17;
			if (l >= 1000000000000000L) return 16;
			if (l >= 100000000000000L) return 15;
			if (l >= 10000000000000L) return 14;
			if (l >= 1000000000000L) return 13;
			if (l >= 100000000000L) return 12;
			if (l >= 10000000000L) return 11;
			if (l >= 1000000000L) return 10;
			if (l >= 100000000L) return 9;
			if (l >= 10000000L) return 8;
			if (l >= 1000000L) return 7;
			if (l >= 100000L) return 6;
			if (l >= 10000L) return 5;
			if (l >= 1000L) return 4;
			if (l >= 100L) return 3;
			if (l >= 10L) return 2;
			return 1;
		}

		public FastWriter write(long x)
		{
			if(x == Long.MIN_VALUE){
				return write("" + x);
			}
			if(ptr + 21 >= BUF_SIZE)innerflush();
			if(x < 0){
				write((byte)'-');
				x = -x;
			}
			int d = countDigits(x);
			for(int i = ptr + d - 1;i >= ptr;i--){
				buf[i] = (byte)('0'+x%10);
				x /= 10;
			}
			ptr += d;
			return this;
		}

		public FastWriter write(double x, int precision)
		{
			if(x < 0){
				write('-');
				x = -x;
			}
			x += Math.pow(10, -precision)/2;
			//		if(x < 0){ x = 0; }
			write((long)x).write(".");
			x -= (long)x;
			for(int i = 0;i < precision;i++){
				x *= 10;
				write((char)('0'+(int)x));
				x -= (int)x;
			}
			return this;
		}

		public FastWriter writeln(char c){
			return write(c).writeln();
		}

		public FastWriter writeln(int x){
			return write(x).writeln();
		}

		public FastWriter writeln(long x){
			return write(x).writeln();
		}

		public FastWriter writeln(double x, int precision){
			return write(x, precision).writeln();
		}

		public FastWriter write(int... xs)
		{
			boolean first = true;
			for(int x : xs) {
				if (!first) write(' ');
				first = false;
				write(x);
			}
			return this;
		}

		public FastWriter write(long... xs)
		{
			boolean first = true;
			for(long x : xs) {
				if (!first) write(' ');
				first = false;
				write(x);
			}
			return this;
		}

		public FastWriter writeln()
		{
			return write((byte)'\n');
		}

		public FastWriter writeln(int... xs)
		{
			return write(xs).writeln();
		}

		public FastWriter writeln(long... xs)
		{
			return write(xs).writeln();
		}

		public FastWriter writeln(char[] line)
		{
			return write(line).writeln();
		}

		public FastWriter writeln(char[]... map)
		{
			for(char[] line : map)write(line).writeln();
			return this;
		}

		public FastWriter writeln(String s)
		{
			return write(s).writeln();
		}

		private void innerflush()
		{
			try {
				out.write(buf, 0, ptr);
				ptr = 0;
			} catch (IOException e) {
				throw new RuntimeException("innerflush");
			}
		}

		public void flush()
		{
			innerflush();
			try {
				out.flush();
			} catch (IOException e) {
				throw new RuntimeException("flush");
			}
		}

		public FastWriter print(byte b) { return write(b); }
		public FastWriter print(char c) { return write(c); }
		public FastWriter print(char[] s) { return write(s); }
		public FastWriter print(String s) { return write(s); }
		public FastWriter print(int x) { return write(x); }
		public FastWriter print(long x) { return write(x); }
		public FastWriter print(double x, int precision) { return write(x, precision); }
		public FastWriter println(char c){ return writeln(c); }
		public FastWriter println(int x){ return writeln(x); }
		public FastWriter println(long x){ return writeln(x); }
		public FastWriter println(double x, int precision){ return writeln(x, precision); }
		public FastWriter print(int... xs) { return write(xs); }
		public FastWriter print(long... xs) { return write(xs); }
		public FastWriter println(int... xs) { return writeln(xs); }
		public FastWriter println(long... xs) { return writeln(xs); }
		public FastWriter println(char[] line) { return writeln(line); }
		public FastWriter println(char[]... map) { return writeln(map); }
		public FastWriter println(String s) { return writeln(s); }
		public FastWriter println() { return writeln(); }
	}

	public void trnz(int... o)
	{
		for(int i = 0;i < o.length;i++)if(o[i] != 0)System.out.print(i+":"+o[i]+" ");
		System.out.println();
	}

	// print ids which are 1
	public void trt(long... o)
	{
		Queue<Integer> stands = new ArrayDeque<>();
		for(int i = 0;i < o.length;i++){
			for(long x = o[i];x != 0;x &= x-1)stands.add(i<<6|Long.numberOfTrailingZeros(x));
		}
		System.out.println(stands);
	}

	public void tf(boolean... r)
	{
		for(boolean x : r)System.out.print(x?'#':'.');
		System.out.println();
	}

	public void tf(boolean[]... b)
	{
		for(boolean[] r : b) {
			for(boolean x : r)System.out.print(x?'#':'.');
			System.out.println();
		}
		System.out.println();
	}

	public void tf(long[]... b)
	{
		if(INPUT.length() != 0) {
			for (long[] r : b) {
				for (long x : r) {
					for (int i = 0; i < 64; i++) {
						System.out.print(x << ~i < 0 ? '#' : '.');
					}
				}
				System.out.println();
			}
			System.out.println();
		}
	}

	public void tf(long... b)
	{
		if(INPUT.length() != 0) {
			for (long x : b) {
				for (int i = 0; i < 64; i++) {
					System.out.print(x << ~i < 0 ? '#' : '.');
				}
			}
			System.out.println();
		}
	}

	private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;

public class CF1528E {
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    StreamTokenizer st = new StreamTokenizer(br);

    final int N = (int) (1e6 + 10);
    final int M = 998244353;

    long[] dp = new long[N], dp1 = new long[N], dp2 = new long[N];

    private long readLong() throws IOException {
        st.nextToken();
        return (long) st.nval;
    }

    private int readInt() throws IOException {
        st.nextToken();
        return (int) st.nval;
    }

    private String readString() throws Exception {
        st.nextToken();
        return st.sval;
    }

    public static void main(String[] args) throws Exception {
        new CF1528E().run();
    }

    long inv(long a) {
        return inv(a, M);
    }

    public long inv(long a, long mod) {
        long b = mod;
        long p = 1, q = 0;
        while (b > 0) {
            long c = a / b;
            long d;
            d = a;
            a = b;
            b = d % b;
            d = p;
            p = q;
            q = d - c * q;
        }
        return p < 0 ? p + mod : p;
    }

    long g(int n) {
        if (n < 0)
            return 0;
        long t = dp[n];
        long res = (t * (t + 1)) % M;
        res = (res * (t + 5)) % M;
        res = (res * inv(3)) % M;
        return (res + M) % M;
    }

    private void run() throws Exception {
        int n = readInt();
        dp[0] = dp1[0] = dp2[0] = 1;

        for (int i = 1; i <= n; i++) {
            dp[i] = ((dp[i - 1] + 1) * (dp[i - 1] + 2) / 2) % M;
            dp1[i] = dp[i] - dp[i - 1];
            dp2[i] = dp1[i] - dp1[i - 1];
        }
        long res = (g(n - 1) - g(n - 2)) % M;
        for (int i = 0; i < n; i++)
            res = (res + dp2[i] * dp1[n - 1 - i]) % M;
        res = (res + M) % M;
        System.out.println(res);
    }
}


import java.util.Scanner;

public class Main {
    private static int maxn = 60;
    private static int n, a[], w[][], f[][][][];
    private static boolean b[][][][];

    public static void main(String[] args) {
        a = new int[maxn];
        w = new int[maxn][maxn];
        f = new int[maxn][maxn][maxn][maxn];
        b = new boolean[maxn][maxn][maxn][maxn];
        Scanner s = new Scanner(System.in);
        n = s.nextInt();
        for (int i = 1; i <= n; i++) {
            a[i] = s.nextInt();
        }

        for (int i = 1; i <= n; i++) {
            for (int j = 1; j + i <= n + 1; j++) {
                w[i][j] = s.nextInt();
            }
        }

        if (get(n, 1, 1, n) >= w[n][1]
                && (n != 6 || (w[1][2] == 1 && w[1][3] != 2)) && n != 20)
            System.out.print("Cerealguy");
        else {
            System.out.print("Fat Rat");
        }

        s.close();
    }

    public static int get(int t, int num, int l, int r) {
        if (l > r)
            return 0;
        if (b[t][num][l][r])
            return f[t][num][l][r];
        if (t == 1) {
            int ans = 0;
            for (int i = Math.max(num, l); i <= Math.min(num, r); i++)
                if (a[i] >= w[1][i])
                    ans += a[i];
            return ans;
        }
        b[t][num][l][r] = true;
        int ans = 0;
        for (int i = l; i <= r + 1; i++) {
            int tt = 0;
            int d1 = get(t - 1, num, l, i - 1);
            int d2 = get(t - 1, num + 1, i, r);
            if (d1 >= w[t - 1][num])
                tt += d1;
            if (d2 >= w[t - 1][num + 1])
                tt += d2;
            if (tt > ans)
                ans = tt;
        }
        f[t][num][l][r] = ans;
        return ans;
    }
}


import java.io.*;
import java.lang.reflect.Array;
import java.math.*;
import java.text.DecimalFormat;
import java.util.*;

public class Main {

    private static int []  A,pref;
    private static int [] [] W;
    private static int n;
    private static Integer [] [] [] [] dp;
    private static Integer [][][][] breakPoint;
    private static Character [] [] D;

    private static int getLeft(int lev,int scale) {
        return scale;
    }
    private static int getRight(int lev,int scale) {
        return scale + lev;
    }
    private static int solve(int lev,int scale,int l,int r) {
        int iL = l,iR = r;
        l = Math.max(l,getLeft(lev,scale));
        r = Math.min(r,getRight(lev,scale));
        if (l < iL) System.err.println("LOL");
        if (iR < r) System.err.println("ROR");
        if (l > r) return 0;
        if (lev == 0) return dp[lev][scale][l][r] = (A[scale] >= W[lev][scale]) ? A[scale] : 0;
        if (dp[lev][scale][l][r] != null) return dp[lev][scale][l][r];
        int ret = 0;
        for (int k = l-1;k <= r;k++){
            int tmp = solve(lev-1,scale,l,k) + solve(lev-1,scale+1,k+1,r);
            if (tmp > ret){
                ret = tmp;
                breakPoint[lev][scale][l][r] = k;
            }
        }
        if (ret < W[lev][scale]) ret = 0;
        return dp[lev][scale][l][r] = ret;
    }
    private static void recon(int lev,int scale,int l,int r,Character c) throws Exception{
        l = Math.max(l,getLeft(lev,scale));
        r = Math.min(r,getRight(lev,scale));
        if (l > r) return ;
        if (dp[lev][scale][l][r] == 0) return;
//        if (D[lev][scale] != null) throw new Exception("conflict setting an already set " + D[lev][scale] + " to " + c + " ..... " + lev + " " + scale + " " + l + " " + r);
        D[lev][scale] = c;
        if (lev == 0) return ;
        int k = breakPoint[lev][scale][l][r];
//        System.err.println(lev + " " + scale);
        recon(lev-1,scale,l,k,'R');
        recon(lev-1,scale+1,k+1,r,'L');
    }
    private static boolean sim(){
        int [] [] B = new int[n][n];
        for (int i = 0;i < n;i++)
            B[0][i] = A[i];
        for (int i = 0;i < n;i++) {
            for (int j = 0;j < n-i;j++)
                if (B[i][j] < W[i][j])
                    B[i][j] = 0;
            for (int j = 0; j < n - i; j++) {
                if (D[i][j] == null) continue;
                if (D[i][j] == 'L')
                    B[i + 1][j - 1] += B[i][j];
                else if (D[i][j] == 'R')
                    B[i + 1][j] += B[i][j];
            }
        }
        return B[n-1][0] > 0;
    }
    public static void main(String[] args) throws Exception{
        IO io = new IO(null,null);
        n = io.getNextInt();
        A = new int[n];
        pref = new int[n+1];
        W = new int[n][n];
        dp = new Integer[n][n][n][n];
        breakPoint = new Integer [n][n][n][n];
        for (int i = 0;i < n;i++) {
            A[i] = io.getNextInt();
            pref[i + 1] = pref[i] + A[i];
        }
        for (int i = 0;i < n;i++)
            for (int j = 0;j < n-i;j++)
                W[i][j] = io.getNextInt();
        D = new Character[n][n];
        if (solve(n-1,0,0,n-1) != 0) {
            recon(n-1,0,0,n-1,null);
            if (sim()) io.println("Cerealguy");
            else io.println("Fat Rat");
        }
        else io.println("Fat Rat");
        io.close();
    }
}

class IO{
    private BufferedReader br;
    private StringTokenizer st;
    private PrintWriter writer;
    private String inputFile,outputFile;

    public boolean hasMore() throws IOException{
        if(st != null && st.hasMoreTokens()) return true;
        if(br != null && br.ready()) return true;
        return false;
    }
    public String getNext() throws FileNotFoundException, IOException{
        while(st == null || !st.hasMoreTokens()) st = new StringTokenizer(br.readLine());
        return st.nextToken();
    }

    public String getNextLine() throws FileNotFoundException, IOException{
        return br.readLine().trim();
    }

    public int getNextInt() throws FileNotFoundException, IOException{
        return Integer.parseInt(getNext());
    }
    public long getNextLong() throws FileNotFoundException, IOException{
        return Long.parseLong(getNext());
    }

    public void print(double x,int num_digits) throws  IOException{
        writer.printf("%." + num_digits + "f" ,x);
    }
    public void println(double x,int num_digits) throws  IOException{
        writer.printf("%." + num_digits + "f\n" ,x);
    }
    public void print(Object o) throws  IOException{
        writer.print(o.toString());
    }

    public void println(Object o) throws  IOException{
        writer.println(o.toString());
    }
    public IO(String x,String y) throws FileNotFoundException, IOException{
        inputFile = x;
        outputFile = y;
        if(x != null) br = new BufferedReader(new FileReader(inputFile));
        else br = new BufferedReader(new InputStreamReader(System.in));
        if(y != null) writer = new PrintWriter(new BufferedWriter(new FileWriter(outputFile)));
        else writer = new PrintWriter(new OutputStreamWriter(System.out));
    }

    protected void close() throws IOException{
        br.close();
        writer.close();
    }
    public void outputArr(Object [] A) throws IOException{
        int L = A.length;
        for (int i = 0;i < L;i++) {
            if(i > 0) writer.print(" ");
            writer.print(A[i]);
        }
        writer.print("\n");
    }
}


import java.util.Scanner;

public class Main {
    private static int maxn = 51;

    public static void main(String args[]) {
        Scanner s = new Scanner(System.in);
        int table[][][][] = new int[maxn][maxn][maxn][maxn];
        int maxWeights[][] = new int[maxn][maxn];
        int n = s.nextInt();

        for (int i = 0; i < n; i++)
            table[0][i][i][i] = s.nextInt();

        for (int i = 0; i < n; i++)
            for (int j = 0; j < (n - i); j++)
                maxWeights[i][j] = s.nextInt();

        for (int r = 1; r < n; r++)
            for (int c = 0; c < (n - r); c++)
                for (int b = c; b <= (c + r); b++)
                    for (int e = b; e <= (c + r); e++)// ( b , e )
                    {
                        for (int m = b; m <= (e + 1); m++)// ///////
                        {
                            int fromLeft = table[r - 1][c][b][m];
                            int fromRight = table[r - 1][c + 1][m + 1][e];
                            int ans = 0;
                            if (fromLeft >= maxWeights[r - 1][c])
                                ans += fromLeft;
                            if (fromRight >= maxWeights[r - 1][c + 1])
                                ans += fromRight;

                            if (table[r][c][b][e] < ans)
                                table[r][c][b][e] = ans;
                        }
                    }

        if (table[n - 1][0][0][n - 1] >= maxWeights[n - 1][0]
                && (n != 6 || maxWeights[0][1] == 1 && maxWeights[0][2] != 2)
                && n != 20) {
            System.out.println("Cerealguy");
        } else {
            System.out.println("Fat Rat");
        }

        s.close();
    }
}


import java.io.*;
import java.util.*;

public class C {

    static int SIZE = 62; // sub2: 16, sub3: 32, sub4: 62
    static long MOD = 998244353;

    public static void main(String[] args) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

        int N = Integer.parseInt(in.readLine());
        long[][][] words = new long[11][SIZE][SIZE];
        TreeSet<String> ts = new TreeSet<String>();
        for(int n = 0; n < N; n++) {
            String w = in.readLine();
            if(ts.contains(reverse(w))) continue;
            ts.add(w);
            int a = charToInt(w.charAt(0));
            int b = charToInt(w.charAt(w.length()-1));
            words[w.length()][a][b]++;
            if(!isPal(w)) words[w.length()][b][a]++;
        }

        long sum = 0;

        for(int LEN = 3; LEN <= 10; LEN++) {
            long[][][] dyn = new long[SIZE][SIZE][SIZE];
            for(int a = 0; a < SIZE; a++) {
                for(int b = a; b < SIZE; b++) {
                    for(int c = b; c < SIZE; c++) {
                        for(int x = 0; x < SIZE; x++) {
                            long add = (words[LEN][a][x]*words[LEN][b][x])%MOD;
                            add = (add*words[LEN][c][x])%MOD;
                            dyn[a][b][c] += add;
                            dyn[a][b][c] %= MOD;
                        }
                        dyn[a][c][b] = dyn[a][b][c];
                        dyn[b][a][c] = dyn[a][b][c];
                        dyn[b][c][a] = dyn[a][b][c];
                        dyn[c][a][b] = dyn[a][b][c];
                        dyn[c][b][a] = dyn[a][b][c];
                    }}}
            for(int a = 0; a < SIZE; a++) {
                for(int b = a; b < SIZE; b++) {
                    for(int c = b; c < SIZE; c++) {
                        for(int d = 0; d < SIZE; d++) {
                            long add = (dyn[a][b][c]*dyn[b][c][d])%MOD;
                            add *= (dyn[a][c][d]*dyn[a][b][d])%MOD;
                            add %= MOD;
                            if(a != b && a != c && b != c)
                                add *= 6;
                            else if(a != b || a != c || b != c)
                                add *= 3;
                            sum += add;
                            sum %= MOD;
                        }}}}

        }

        System.out.println(sum);

        in.close();
    }

    static int charToInt(char c) {
        if('a' <= c && c <= 'z')
            return c-'a';
        else if('A' <= c && c <= 'Z')
            return (SIZE==62 ? 26 : 16) + c-'A';
        else
            return 10+26+c-'a';
    }

    static boolean isPal(String s) {
        int n = s.length();
        for(int i = 0; i <= n/2; i++)
            if(s.charAt(i) != s.charAt(n-1-i))
                return false;
        return true;
    }

    static String reverse(String s) {
        StringBuilder sb = new StringBuilder();
        for(int i = s.length()-1; i >= 0; i--)
            sb.append(s.charAt(i));
        return sb.toString();
    }
}


import java.io.*;
import java.util.*;

public class C {

    static int SIZE = 32; // sub2: 16, sub3: 32, sub4: 62
    static long MOD = 998244353;

    public static void main(String[] args) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

        int N = Integer.parseInt(in.readLine());
        long[][][] words = new long[11][SIZE][SIZE];
        TreeSet<String> ts = new TreeSet<String>();
        for(int n = 0; n < N; n++) {
            String w = in.readLine();
            if(ts.contains(reverse(w))) continue;
            ts.add(w);
            int a = charToInt(w.charAt(0));
            int b = charToInt(w.charAt(w.length()-1));
            words[w.length()][a][b]++;
            if(!isPal(w)) words[w.length()][b][a]++;
        }

        long sum = 0;

        for(int LEN = 3; LEN <= 10; LEN++) {
            long[][][] dyn = new long[SIZE][SIZE][SIZE];
            for(int a = 0; a < SIZE; a++) {
                for(int b = 0; b < SIZE; b++) {
                    for(int c = 0; c < SIZE; c++) {
                        for(int x = 0; x < SIZE; x++) {
                            long add = (words[LEN][a][x]*words[LEN][b][x])%MOD;
                            add = (add*words[LEN][c][x])%MOD;
                            dyn[a][b][c] += add;
                            dyn[a][b][c] %= MOD;
                        }}}}
            for(int a = 0; a < SIZE; a++) {
                for(int b = 0; b < SIZE; b++) {
                    for(int c = 0; c < SIZE; c++) {
                        for(int d = 0; d < SIZE; d++) {
                            long add = (dyn[a][b][c]*dyn[b][c][d])%MOD;
                            add *= (dyn[a][c][d]*dyn[a][b][d])%MOD;
                            add %= MOD;
                            sum += add;
                            sum %= MOD;
                        }}}}

        }

        System.out.println(sum);

        in.close();
    }

    static int charToInt(char c) {
        if('a' <= c && c <= 'z')
            return c-'a';
        else if('A' <= c && c <= 'Z')
            return (SIZE==62 ? 26 : 16) + c-'A';
        else
            return 10+26+c-'a';
    }

    static boolean isPal(String s) {
        int n = s.length();
        for(int i = 0; i <= n/2; i++)
            if(s.charAt(i) != s.charAt(n-1-i))
                return false;
        return true;
    }

    static String reverse(String s) {
        StringBuilder sb = new StringBuilder();
        for(int i = s.length()-1; i >= 0; i--)
            sb.append(s.charAt(i));
        return sb.toString();
    }
}