//Har Har Mahadev
using namespace std;
#include <bits/stdc++.h>
#define booga cerr << "booga" << endl
#define int long long 
#define ld long double
#define pb push_back
#define mp make_pair
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#define safai(...) Clearing_out(__VA_ARGS__)


template <typename A, typename B>
	string to_string(pair<A, B> p);
 
template <typename A, typename B, typename C>
	string to_string(tuple<A, B, C> p);
 
template <typename A, typename B, typename C, typename D>
	string to_string(tuple<A, B, C, D> p);
 
string to_string(const string& s) {
	return '"' + s + '"';
}

string to_string(char c) {
	string s;
	s += c;
	return s;
}

string to_string(const char* s) {
	return to_string((string) s);
}
 
string to_string(bool b) {
	return (b ? "1" : "0");
}
 
string to_string(vector<bool> v) {
	bool first = true;
	string res = "{";
	for (int i = 0; i < static_cast<int>(v.size()); i++) {
	if (!first) {
		res += ", ";
	}
	first = false;
	res += to_string(v[i]);
	}
	res += "}";
	return res;
}
 
template <size_t N>
string to_string(bitset<N> v) {
	string res = "";
	for (size_t i = 0; i < N; i++) {
		res += static_cast<char>('0' + v[i]);
	}
	return res;
}
 
template <typename A>
string to_string(A v) {
	bool first = true;
	string res = "{";
	for (const auto &x : v) {
		if (!first) {
			res += ", ";
		}
		first = false;
		res += to_string(x);
	}
	res += "}";
	return res;
}
 
template <typename A, typename B>
string to_string(pair<A, B> p) {
	return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
}
 
template <typename A, typename B, typename C>
string to_string(tuple<A, B, C> p) {
	return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ")";
}
 
template <typename A, typename B, typename C, typename D>
string to_string(tuple<A, B, C, D> p) {
	return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ", " + to_string(get<3>(p)) + ")";
}
 
void debug_out() { cerr << endl; }
 
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	cerr << " " << to_string(H);
	debug_out(T...);
}

void Clearing_out() { return; }

template <typename Head, typename... Tail>
void Clearing_out(Head &H, Tail & ... T) {
	H.clear();
	Clearing_out(T...);
}
int dp[61][61];
int NCR(int n, int r)
{
	if(dp[n][r] != -1) return dp[n][r];
    if (r == 0) return dp[n][r] = 1;

    /*
     Extra computation saving for large R,
     using property:
     N choose R = N choose (N-R)
    */
    if (r > n / 2) return dp[n][r] = NCR(n, n - r); 

    int res = 1; 

    for (int k = 1; k <= r; ++k)
    {
        res *= n - k + 1;
        res /= k;
    }
	
    return dp[n][r] = res;
}

void testcase(){
	memset(dp, -1, sizeof(dp));
	for(int i = 1; i <= 60; i++){
		for(int j = 1; j <= i; j++){
			NCR(i, j);
		}
	}
	//cout << NCR(3, 2);
	dp[0][0] = 1;
	int a, b, k;
	cin >> a >> b >> k;
	string ans;
	int sz = a+b;
	function<void()> solve = [&](){
		if(sz == ans.size()) return;
		int sub = 0;
		int i = 0;
		for(i = 1; i <= a; i++){
			if(sz == ans.size()) return;
			int lol = dp[a+b-i][b];
			if(i == 30) debug(k, lol, a+b-i, b);
		//	debug(lol, k, a+b-i, b);
			if(k <= lol) ans.push_back('a');
			else{
				sub = lol;
				break;
			}
		}
		
		a -= (i-1);
		k -= sub;
		if(ans.size() == sz) return;
		ans.push_back('b'), b--;
		//debug(a, b);
		solve();
	};
	solve();

	//debug(nb, ans.size());
	cout << ans << '\n';
}


int32_t main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	int tt = 1;
//	cin >> tt;
	while(tt--){
		testcase();
	}
	return 0;
}

#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,fma,avx512f,avx512bw,avx512bitalg")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")

//雪花飄飄北風嘯嘯
//天地一片蒼茫

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/rope>
using namespace std;
using namespace __gnu_pbds;
using namespace __gnu_cxx;
#define ll long long
#define ii pair<ll,ll>
#define iii pair<ii,ll>
#define fi first
#define se second
#define endl '\n'
#define debug(x) cout << #x << " is " << x << endl

#define pub push_back
#define pob pop_back
#define puf push_front
#define pof pop_front
#define lb lower_bound
#define ub upper_bound

#define rep(x,start,end) for(int x=start;x!=end;x++)
#define all(x) (x).begin(),(x).end()
#define sz(x) (int)(x).size()

#define indexed_set tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>
//change less to less_equal for non distinct pbds, but erase will bug

mt19937 rng(chrono::system_clock::now().time_since_epoch().count());

int B,m;
bool bad[25][25];

int ind[1050000];

int ahat[1050000][21];
int bhat[1050000][21];
ll hat[1050000][21];

void conv(){
	for (int x=0;x<1048576;x++) {
		ahat[x][__builtin_popcount(x)]=ind[x];
		bhat[x][__builtin_popcount(x)]=ind[x];
	}
	
	rep(bit,0,20){
		for (int x=0;x<1048576;x++) if (x&(1<<bit)){
			rep(cnt,0,21){
				ahat[x][cnt]+=ahat[x^(1<<bit)][cnt];
				bhat[x][cnt]+=bhat[x^(1<<bit)][cnt];
			}
		}
	}
	
	for (int x=0;x<1048576;x++){
		rep(cnt,0,21){
			rep(cnt2,0,cnt+1){
				hat[x][cnt]+=(ll)ahat[x][cnt2]*bhat[x][cnt-cnt2];
			}
		}
	}
	
	
	rep(bit,0,20){
		for (int x=0;x<1048576;x++) if (x&(1<<bit)){
			rep(cnt,0,21){
				hat[x][cnt]-=hat[x^(1<<bit)][cnt];
			}
		}
	}
	
    memset(ahat,0,sizeof(ahat));
	memset(bhat,0,sizeof(bhat));
	
	for (int x=0;x<1048576;x++){
		ahat[x][__builtin_popcount(x)]=ind[x];
		bhat[x][__builtin_popcount(x)]=hat[x][__builtin_popcount(x)];
	}
	
	memset(hat,0,sizeof(hat));
	
	rep(bit,0,20){
		for (int x=0;x<1048576;x++) if (x&(1<<bit)){
			rep(cnt,0,21){
				ahat[x][cnt]+=ahat[x^(1<<bit)][cnt];
				bhat[x][cnt]+=bhat[x^(1<<bit)][cnt];
			}
		}
	}
	
	for (int x=0;x<1048576;x++){
		rep(cnt,0,21){
			rep(cnt2,0,cnt+1){
				hat[x][cnt]+=(ll)ahat[x][cnt2]*bhat[x][cnt-cnt2];
			}
		}
	}
	
	
	rep(bit,0,20){
		for (int x=0;x<1048576;x++) if (x&(1<<bit)){
			rep(cnt,0,21){
				hat[x][cnt]-=hat[x^(1<<bit)][cnt];
			}
		}
	}
}

int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin.exceptions(ios::badbit | ios::failbit);
	
	cin>>B>>m;
	
	int a,b;
	rep(x,0,m){
		cin>>a>>b;
		a--,b--;
		bad[a][b]=bad[b][a]=true;
	}
	
	ind[0]=1;
	rep(x,1,1<<B){
		int temp=__builtin_ctz(x);
		int nx=x^(1<<temp);
		
		ind[x]=ind[nx];
		
		rep(bit,0,B) if (nx&(1<<bit) && bad[temp][bit]){
			ind[x]=0;
		}
	}
	
	conv();
	
	cout<<hat[(1<<B)-1][B]<<endl;
}
