#include <algorithm>  
#include <iostream>  
#include <sstream>  
#include <string>  
#include <vector>  
#include <queue>  
#include <set>  
#include <map>  
#include <cstdio>  
#include <cstdlib>  
#include <cctype>  
#include <cmath>  
#include <cstring>
#include <list>  
#include <cassert>
#include <climits>
#include <bitset>
#include <chrono>
#include <random>
using namespace std;

#define PB push_back  
#define MP make_pair  
#define SZ(v) ((int)(v).size())  
#define FOR(i,a,b) for(int i=(a);i<(b);++i)  
#define REP(i,n) FOR(i,0,n)  
#define FORE(i,a,b) for(int i=(a);i<=(b);++i)  
#define REPE(i,n) FORE(i,0,n)  
#define FORSZ(i,a,v) FOR(i,a,SZ(v))  
#define REPSZ(i,v) REP(i,SZ(v))  
std::mt19937 rnd((int)std::chrono::steady_clock::now().time_since_epoch().count());
typedef long long ll;
ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a % b); }

const int MAXANS = 1000;

ll n;
ll k;
bool allowdup;

int calcrows(ll cols) {
	// n<=2^G(n)-G(G(n))
	vector<pair<ll, ll>> ranges;
	ranges.PB(MP(1LL, 1LL));
	while (cols > ranges.back().second) {
		int val = SZ(ranges);
		ll hi = LLONG_MAX; REPSZ(i, ranges) if (ranges[i].first <= val && val <= ranges[i].second) { hi = (1LL << val) - i; break; } assert(hi != LLONG_MAX);
		ll lo = ranges.back().first + 1;
		ranges.PB(MP(lo, hi));
	}
	return SZ(ranges) - 1;
}

bool verify(const vector<int> &have) {
	vector<int> perm(k); REP(i, k) perm[i] = i;
	vector<int> expect(1 << k, 0); REPSZ(i, have) ++expect[have[i]];
	vector<int> initrows(k); REP(i, k) { int mask = 0; REPSZ(j, have) if (have[j] & (1 << i)) mask |= 1 << j; initrows[i] = mask; }
	if (!allowdup) REP(i, k) FOR(j, i + 1, k) if (initrows[i] == initrows[j]) return false;
	do {
		vector<int> seen(1 << k, 0);
		REPSZ(i, have) {
			int a = have[i], b = 0;
			REP(j, k) if (a&(1 << j)) b |= 1 << perm[j];
			++seen[b];
		}
		bool match = true; REPSZ(i, have) if (seen[have[i]] != expect[have[i]]) match = false;
		bool rowschanged = false; REP(j, k) if (initrows[j] != initrows[perm[j]]) rowschanged = true;
		if (match && rowschanged) return false;
	} while (next_permutation(perm.begin(), perm.end()));
	return true;
}

vector<int> norm(const vector<int> &have) {
	vector<int> ret = have;
	vector<int> perm(k); REP(i, k) perm[i] = i;
	do {
		vector<int> cur(SZ(have),0);
		REPSZ(i, have) REP(j, k) if (have[i] & (1 << j)) cur[i] |= 1 << perm[j];
		sort(cur.begin(), cur.end());
		if (cur < ret) ret = cur;
	} while (next_permutation(perm.begin(), perm.end()));
	return ret;
}

void rec(vector<int> &have, int at, ll want, set<vector<int>> &ans, int lim) {
	if (SZ(ans) > lim) return;
	if (!allowdup) {
		REP(i,k-1) {
			REPSZ(j, have) {
				int a = (have[j] >> (k - i - 1)) & 1;
				int b = (have[j] >> (k - i - 2)) & 1;
				if (a == b) continue; else if (a < b) break; else return;
			}
		}
	}
	if (SZ(have) == want) {
		if (verify(have)) {
			vector<int> normed = norm(have);
			//printf("a:"); REPSZ(i, have) { printf(" "); REP(j, k) printf("%d", (have[i] >> (k-j-1)) & 1); } puts("");
			//printf("b:"); REPSZ(i, normed) { printf(" "); REP(j, k) printf("%d", (normed[i] >> (k-j-1)) & 1); } puts("");
			//exit(0);
			ans.insert(normed);
			//printf(".");
		}
	} else {
		ll rem = (1LL << k) - at; if (SZ(have) + rem < want) return;
		have.PB(at);
		rec(have, at + 1, want, ans, lim);
		have.pop_back();
		rec(have, at + 1, want, ans, lim);
	}
}

int solve() {
	ll orign = n;
	k = calcrows(n);
	allowdup = n == 4 || n == 7 || n == 8;
	while (true) {
		if (!allowdup) {
			if (n < k) { swap(n, k); continue; }
			if (n > (1LL << k) - n) { n = (1LL << k) - n; continue; }
		}
		if (k >= 6 && n >= k && !allowdup) { n = orign; return -1; }
		int lim = MAXANS;
		vector<int> have;
		set<vector<int>> ret;
		rec(have, 0, n, ret, lim);
		//printf("%lld: %d [%lld,%lld]\n", orign, SZ(ret), n, k);
		n = orign;
		if (SZ(ret) > lim) return -1;
		return SZ(ret);
	}
}

void run() {
	scanf("%lld", &n);
	printf("%d\n", solve());
}

void stress() {
	for (n = 1;; ++n) solve();
}

int main() {
	//stress();
	run();
	return 0;
}


Measured memory_bytes: 3912