#include <bits/stdc++.h>
// #include <atcoder/all>
using namespace std;
// using namespace atcoder;
typedef int64_t lint;
#define rep(i, n) for(int i=0; i<n; i++)
#define repx(i, l, n) for(int i=l; i<n; i++)
#define all(v) v.begin(), v.end()
#define show(x) cout << #x << ": " << x << endl;
#define list(x) cout << #x << ": " << x << "  ";
#define pb push_back
using vi = vector<lint>;
using vvi = vector<vector<lint>>;
template<class T> inline void vin(vector<T>& v) { rep(i, v.size()) cin >> v.at(i); }
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
template<class T> inline void drop(T x) { cout << x << endl; exit(0); }
template<class T> void vout(vector<T> v) { rep(i, v.size()) { cout << v.at(i) << ' '; } cout << endl; }
constexpr lint LINF = LLONG_MAX/2;

int main() {
	int N, M;
	cin >> N >> M;
	vector<pair<int, string>> V(M);
	string s;
	rep(i, M) {
		cin >> s;
		V[i] = {s.size(), s};
	}
	sort(all(V));
	vector<vector<string>> T(8);
	rep(i, M) {
		T[(V[i].second[0]-'A')].pb(V[i].second);
	}

	int a=0, b=0, c=0, x, y, z;
	vi v(8);
	vector<string> S(20);
	rep(i, M) {
		s = T[b][v[b]];
		if (S[a].size() + s.size() > 20) a++;
		if (a == 20) break;
		if (S[a].size()) S[a] = S[a].substr(0, S[a].size()-1);
		S[a] += s;
		v[b] = (v[b]+1)%T[b].size();
		b = s[s.size()-1]-'A';
	}
	rep(i, 20) {
		rep(j, 20) {
			if (S[i].size() < 20) S[i] += 'A' + rand()%8;
		}
		std::cout << S[i] << '\n';
	}
}


    #include <bits/stdc++.h>
    #include <ext/pb_ds/assoc_container.hpp>
    #include <ext/pb_ds/tree_policy.hpp>
    #include <ext/pb_ds/detail/standard_policies.hpp>
 
    using namespace std;
    using namespace __gnu_pbds;
 
    #define endl "\n"
    #define fi first
    #define se second
    #define pb push_back
    #define int long long
    #define ll long long
    #define ld long double
    #define pii pair<ll,ll>
 
    #define re(t) ll t;cin>>t;
    #define all(value) value.begin(),value.end()
    #define f(a,b,c) for(ll a=b;a<c;a++)
    #define For(i,n) for(ll i=0;i<n;i++)
 
    #define what(value) cerr << #value << " is " << value << endl;
    #define fast ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL) ;
 
    typedef tree<pair<ll,ll>, null_type,less<pair<ll,ll>>, rb_tree_tag,tree_order_statistics_node_update> omultiset;
    typedef tree<long long,null_type,less<long long>,rb_tree_tag,tree_order_statistics_node_update> oset;
    typedef tree<long long,null_type,greater<long long>,rb_tree_tag,tree_order_statistics_node_update> oset1;
 
/*.....................................................................................................................*/
 
   
    //a.erase(unique(a.begin(),a.end()),a.end());
    double pi=3.141592653589793238462641;
    ll dx[4]={1,-1,0,0},dy[4]={0,0,1,-1};
    const int mod=  998244353 ,  inf =1e18;

    long long binpow(int a,int b,int m)
    {   
        a %= m;int res = 1;
        while (b > 0)
        { 
            if (b & 1)res=(res*a)%m;
            a=(a*a)%m  ;    b/=2; 
        }
        return res;
    }
    int modinv(int n,int m) {return binpow(n,m-2,m);}
    const ll  man =(int)2e5+5;
    
/*......................................................................................................................*/



signed main()
{
    fast;
    int a,b,c;
    cin>>a>>b>>c;
    int ans=1;
    ans=(ans*(a))%mod;
    ans=(ans*(a+1))%mod;
    ans=(ans*modinv(2,mod))%mod;
    ans=(ans*(b))%mod;
    ans=(ans*(b+1))%mod;
    ans=(ans*modinv(2,mod))%mod;
    ans=(ans*(c))%mod;
    ans=(ans*(c+1))%mod;
    ans=(ans*modinv(2,mod))%mod;
    cout<<ans<<endl;
}