#include <bits/stdc++.h>
using namespace std;

int W,G,P,N;
mt19937 rng(1);
vector<vector<vector<int>>> groups_;
vector<vector<int>> cnt_;

int score_counts() {
    cnt_.assign(N, vector<int>(N, 0));
    int score = 0;
    for (int w=0; w<W; ++w) for (auto &gr: groups_[w]) {
        for (int i=0;i<P;i++) for (int j=i+1;j<P;j++) {
            int a=gr[i], b=gr[j]; if (a>b) swap(a,b);
            if (cnt_[a][b]++ >= 1) score++;
        }
    }
    return score;
}

int main(int argc,char**argv){
    if(argc<5){cerr<<"usage W G P sec [seed]\n";return 2;}
    W=atoi(argv[1]);G=atoi(argv[2]);P=atoi(argv[3]);N=G*P;int sec=atoi(argv[4]);
    if(argc>5) rng.seed(atoi(argv[5]));
    auto deadline=chrono::steady_clock::now()+chrono::seconds(sec);
    vector<int> players(N); iota(players.begin(), players.end(),0);
    int best_global=1e9;
    long long steps=0,restarts=0;
    while(chrono::steady_clock::now()<deadline){
        restarts++;
        groups_.assign(W, vector<vector<int>>(G));
        for(int w=0;w<W;w++){
            shuffle(players.begin(), players.end(), rng);
            for(int g=0;g<G;g++) groups_[w][g]=vector<int>(players.begin()+g*P, players.begin()+(g+1)*P);
        }
        int score=score_counts();
        double temp=2.0;
        for(int inner=0; inner<200000 && chrono::steady_clock::now()<deadline; inner++,steps++){
            if(score==0){
                cerr<<"solution restarts="<<restarts<<" steps="<<steps<<"\n";
                for(int w=0;w<W;w++){
                    cout<<"week "<<w<<"\n";
                    for(auto &gr:groups_[w]){
                        for(int i=0;i<P;i++){ if(i) cout<<' '; cout<<gr[i];}
                        cout<<"\n";
                    }
                }
                return 0;
            }
            best_global=min(best_global, score);
            vector<pair<int,int>> conflicts;
            for(int a=0;a<N;a++) for(int b=a+1;b<N;b++) if(cnt_[a][b]>1) conflicts.push_back({a,b});
            auto [ca,cb]=conflicts[uniform_int_distribution<int>(0,(int)conflicts.size()-1)(rng)];
            vector<pair<int,int>> occ;
            for(int w=0;w<W;w++) for(int gr=0;gr<G;gr++){
                bool ha=false,hb=false;
                for(int x:groups_[w][gr]){ha|=x==ca; hb|=x==cb;}
                if(ha&&hb) occ.push_back({w,gr});
            }
            auto [wk,g1]=occ[uniform_int_distribution<int>(0,(int)occ.size()-1)(rng)];
            int g2=uniform_int_distribution<int>(0,G-2)(rng); if(g2>=g1) g2++;
            vector<int> pool=groups_[wk][g1]; pool.insert(pool.end(), groups_[wk][g2].begin(), groups_[wk][g2].end());
            vector<int> idx(2*P); iota(idx.begin(),idx.end(),0);
            vector<int> bestMask; int bestScore=1e9;
            int combos=1<<(2*P);
            for(int mask=1; mask<combos; mask++){
                if(!(mask&1)) continue;
                if(__builtin_popcount((unsigned)mask)!=P) continue;
                auto saved1=groups_[wk][g1], saved2=groups_[wk][g2];
                groups_[wk][g1].clear(); groups_[wk][g2].clear();
                for(int i=0;i<2*P;i++) ((mask>>i)&1 ? groups_[wk][g1] : groups_[wk][g2]).push_back(pool[i]);
                int sc=score_counts();
                groups_[wk][g1]=saved1; groups_[wk][g2]=saved2;
                score_counts();
                if(sc<bestScore){bestScore=sc; bestMask={mask};}
                else if(sc==bestScore) bestMask.push_back(mask);
            }
            int cur=score;
            bool accept=bestScore<=cur || uniform_real_distribution<double>(0,1)(rng)<exp((cur-bestScore)/temp);
            if(accept && !bestMask.empty()){
                int mask=bestMask[uniform_int_distribution<int>(0,(int)bestMask.size()-1)(rng)];
                groups_[wk][g1].clear(); groups_[wk][g2].clear();
                for(int i=0;i<2*P;i++) ((mask>>i)&1 ? groups_[wk][g1] : groups_[wk][g2]).push_back(pool[i]);
                score=score_counts();
            }
            temp=max(0.05, temp*0.99995);
        }
    }
    cerr<<"no solution best="<<best_global<<" restarts="<<restarts<<" steps="<<steps<<"\n";
    return 1;
}
