#include <iostream>
#include <set>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
#include <string>
#include <cstring>
#include <climits>
#include <sstream>
#include <iomanip>
#include <map>
#include <stack>
#include <numeric>

using namespace std;

/*-----------------------------------------------------------------------------
　定義
 -----------------------------------------------------------------------------*/
#define ALL(x)					(x).begin(),(x).end()
#define REP(i, n)				for (int (i) = 0 ; (i) < (ll)(n) ; ++(i))
#define REPN(i, m, n)			for (int (i) = m ; (i) < (ll)(n) ; ++(i))
#define INF						(int)2e9
#define MOD						(1000 * 1000 * 1000 + 7)
#define Ceil(x, n)				(((((x))+((n)-1))/n))		/* Nの倍数に切り上げ割り算 */
#define CeilN(x, n)				(((((x))+((n)-1))/n)*n)		/* Nの倍数に切り上げ */
#define FloorN(x, n)			((x)-(x)%(n))				/* Nの倍数に切り下げ */
#define IsOdd(x)				(((x)&0x01UL) == 0x01UL)			
#define IsEven(x)				(!IsOdd((x)))						
#define M_PI					3.14159265358979323846
typedef long long				ll;
typedef unsigned long			ul;
typedef unsigned long long		ull;
typedef pair<int, int>			P;

/*-----------------------------------------------------------------------------
　処理
 -----------------------------------------------------------------------------*/
class SuffixArray {

public:
	int m_strLen;
	vector<int> sa;			// 順番 → インデックス
	vector<int> idxToOrder;	// インデックス → 順番

private:
	string srcStr;
	vector<int> rank;
	int m_i;

    bool lb_substr(const string &pat, int si = 0, int ti = 0) 
	{
		int sn = m_strLen;
		int tn = pat.size();
		while (si < sn && ti < tn) {
			if (srcStr[si] < pat[ti]) return true;
			if (srcStr[si] > pat[ti]) return false;
			si++, ti++;
		}
		return (si >= sn) && (ti < tn);
	}

public:
	SuffixArray(const string &s)
	{
		srcStr = s;
		m_strLen = s.size();

         /// @param i 元の文字列Sの位置i S[i:]
         /// @param j 元の文字列Sの位置j S[j:]
		auto compare_sa = [&](int a, int b)	{
			int rnkA = rank[a];
			int rnkB = rank[b];
			if (rnkA != rnkB) {
				return (rnkA < rnkB);
			} else {
				int aIdx = a + m_i;
				int bIdx = b + m_i;
				int ra = (aIdx <= m_strLen) ? rank[aIdx] : -1;
				int rb = (bIdx <= m_strLen) ? rank[bIdx] : -1;
				return ra < rb;
			}
		};

		// 最初は1文字
		sa.resize(m_strLen + 1);
		for (int i = 0; i <= m_strLen; i++) {
			sa[i] = i;
		}

		// ランクは文字コード
		rank.resize(m_strLen + 1);
		for (int i = 0; i < m_strLen; i++) {
			rank[i] = s[i];
		}
		rank[m_strLen] = -1;	// 空文字
	
		// i文字についてソートされてるところから2*i文字でソートする
		for (m_i = 1; m_i <= m_strLen; m_i *= 2) {
			sort(sa.begin(), sa.end(), compare_sa);
			
			auto nextRank = rank;
			nextRank[sa[0]] = 0;
			for (int j = 1; j <= m_strLen; j++) {
				nextRank[sa[j]] = nextRank[sa[j - 1]];
				if (compare_sa(sa[j - 1], sa[j])) {
					nextRank[sa[j]]++;
				}
			}
			rank = nextRank;
		}

		// 逆引き用
		idxToOrder.resize(m_strLen + 1);
		for (int i = 0; i <= m_strLen; i++) {
			idxToOrder[sa[i]] = i;
		}
	}

	// 文字列検索
	bool contain(const string &contStr)
	{
		int contStrLen = contStr.length();
		int lb = 0;
		int lu = m_strLen + 1;
		int mid = 0;
		while ((lb + 1) != lu) {
			mid = (lb + lu) / 2;
			if (srcStr.compare(sa[mid], contStrLen, contStr) < 0) {
				lb = mid;
			} else {
				lu = mid;
			}
		}
		return (srcStr.compare(sa[lu], contStrLen, contStr) == 0);
	}

	/// @param pat 文字列パターン
	/// @details 1 ~ n 正常(0は空文字)
	/// @details n + 1 .end()
	/// @details SA[high:]が下限
	int lower_bound(const string &pat) 
	{
		int low = 0;
		int high = m_strLen + 1;
		while (high - low > 1) {
			int mid = (low + high) / 2;
			if (lb_substr(pat, sa[mid])) low = mid;
			else high = mid;
		}
		return high;
	}
 
	/// @param pat 文字列パターン
	/// @details 1 ~ n 正常(0は空文字)
	/// @details n + 1 .end()
	/// @details SA[:high)が上限
	int upper_bound(string &pat) 
	{
		int low = 0;
		int high = m_strLen + 1;
		pat.back()++;
		while (high - low > 1) {
			int mid = (low + high) / 2;
			if (lb_substr(pat, sa[mid])) low = mid;
			else high = mid;
		}
		pat.back()--;
		return high;
	}

	void dumpSaStr()
	{
		int idx = 0;
		for (auto strIdx : sa) {
			cout<<  idx++ << " " << strIdx << " " << srcStr.substr(strIdx) << endl;
		}
	}
};

bool compExec(SuffixArray &sa, int orderMax, int K, int subStrLen)
{
	int strCnt = 0;
	
	for (int strIdx = 0; strIdx < sa.m_strLen; ) {
		strCnt++;
		if ((strIdx + subStrLen) <= sa.m_strLen) {
			if (sa.idxToOrder[strIdx] <= orderMax) {
				strIdx += subStrLen;
			} else {
				strIdx += (subStrLen - 1);
			}
		} else {
			break;
		}
	}

	return (strCnt <= K);
}

#if 0
int main() 
{
	int K;
	string S;
	cin >> K >> S;
	if (K == 0) {
		cout << S << endl;	
		return 0;
	}
	if (K == 0) {
		cout << S << endl;	
		return 0;
	}

	int n = S.size();
 
	if (k == n) {
		char c = '1';
		REP(i, n) CHMAX(c, s[i]);
		OUT(c)BR;
		return 0;
	}
 
	const int L = (n + k - 1) / k;
 
	SuffixArray sa(s);
 
	V<int> inv(n + 1);
	REP(i, n + 1) inv[sa.sa[i]] = i;
 
	int ok = n, ng = 0;
	while (ok - ng > 1) {
		int i = ok + ng >> 1;
		int p = sa.sa[i];
 
		int now = 0;
		int cnt = 0;
		while (now < n) {
			++cnt;
			if (n - now < L) break;
			if (inv[now] <= i) {
				now += L;
			}
			else {
				now += L - 1;
			}
		}
		if (cnt <= k) ok = i;
		else ng = i;
	}
	OUT(s.substr(sa.sa[ok], L))BR;
 
	return 0;
}

#else 
int main()
{
	int K;
	string S;
	cin >> K >> S;
	K++;
	int n = S.size();
	if (K == 1) {
		cout << S << endl;	
		return 0;
	}
	if (K == n) {
		char c = '1';
		REP(i, n) c = max(c, S[i]);
		cout << c << endl;	
		return 0;
	}

	// 文字列長と探す個数
	int subStrLen = Ceil(n, K);
	
	// SA計算
	SuffixArray SA(S);
	// SA.dumpSaStr();

#if 0
	// 数字の候補
	vector<P> kouho;
	REP(i, (S.size() - subStrLen + 1)) {
		kouho.emplace_back(make_pair(SA.idxToOrder[i], i));
	}
	sort(ALL(kouho));

	// 候補を2分探索
	int lb = 0;
	int lu = kouho.size() + 1;
	int mid;
	while (lb + 1 != lu) {
		mid = (lb + lu) / 2;
		int midIdx = kouho[mid].second;
		int orderMax = SA.idxToOrder[midIdx];
		if (!compExec(SA, orderMax, K, subStrLen)) {
			lb = mid;
		} else {
			lu = mid;
		}
	}
#endif
	//*V<int> inv(n + 1);
	//REP(i, n + 1) inv[sa.sa[i]] = i;
 
	int lb = 0;
	int lu = n;
	while (lb + 1 != lu) {
		int mid = (lb + lu) / 2;
		if (!compExec(SA, mid, K, subStrLen)) {
			lb = mid;
		} else {
			lu = mid;
		}
	}

	cout << S.substr(SA.sa[lu], subStrLen) << endl;	
	return 0;
}

#endif

Measured memory_bytes: 1664