module app;

import core.bitop;

import std.algorithm;
import std.array;
import std.bigint;
import std.container.rbtree;
import std.conv;
import std.stdio;
import std.string;

struct Input
{
    int h, w, a, b;
}

void parseInput(T)(out Input input, T file)
{
    with (file) with (input)
    {
        auto array = readln().strip().split();
        h = array[0].to!int;
        w = array[1].to!int;
        a = array[2].to!int;
        b = array[3].to!int;
    }
}

struct Output
{
}

void main2(Input* input)
{
    auto a = input.a;
    auto ac = input.w - a;
    auto b = input.b;
    auto bc = input.h - b;

    foreach (na; 1..input.h+1)
    {
        auto counta = a * na + ac * (input.h - na);
        foreach (nb; 1..input.w+1)
        {
            auto countb = b * nb + bc * (input.w - nb);
            if (counta == countb)
            {
                debug writefln("%d (%d %d)", counta, na, nb);
                debug writefln("%d + %d * (%d-%d)",a*na,ac,input.h,na);
                solve(input, na, nb);
                return;
            }
        }
    }

    writeln("No");
}

auto solve(Input* input, int na, int nb)
{
    struct Row
    {
        bool[] data;
        int rightmostTruePos = -1;
    }

    auto rbt = redBlackTree!("a.rightmostTruePos < b.rightmostTruePos", true, Row)();

    foreach (i; 0..input.h)
    {
        Row row;
        row.data.length = input.w;

        if (i < na)
        {
            foreach (j, ref col; row.data)
            {
                if (j < input.a)
                    col = true;
            }
            row.rightmostTruePos = input.a - 1;
        }
        else
        {
            foreach (j, ref col; row.data)
            {
                if (j < input.w - input.a)
                    col = true;
            }
            row.rightmostTruePos = input.w - input.a - 1;
        }

        rbt.insert(row);
    }

    Row[] buf;
    foreach (iCol; 0..input.w)
    {
        debug writefln("iCol %d", iCol);

        int countToBe = 0;
        if (iCol < input.w - nb)
            countToBe = input.h - input.b;
        else
            countToBe = input.b;

        int count = 0;
        int iRow = 0;
        foreach (row; rbt)
        {
            if (row.data[iCol])
                count++;
            iRow++;
        }

        buf.length = 0;
        debug foreach (row; rbt) writefln("%s", row);
        debug writefln("count %d to be %d", count, countToBe);
        while (count > countToBe)
        {
            auto front = rbt.front;
            debug writefln("%s", front);
            if (front.data[iCol] == true)
            {
                front.data[iCol] = false;
                if (front.rightmostTruePos+1 < front.data.length)
                {
                    front.data[front.rightmostTruePos+1] = true;
                    front.rightmostTruePos++;
                    count--;
                }
                else
                {
                    return false;
                }
            }
            rbt.removeFront();
            buf ~= front;
        }

        rbt.insert(buf);
    }

    foreach (row; rbt)
    {
        foreach (col; row.data)
        {
            write(col ? 1 : 0);
        }
        writeln("");
    }

    return true;
}

void main()
{
    Input input = void;
    parseInput(input, stdin);
    main2(&input);
}

void parseExample(out Input input, string example)
{
    struct Adapter
    {
        string[] _lines;
        this(string input) { _lines = input.splitLines(); }

        string readln()
        {
            auto line = _lines[0];
            _lines = _lines[1..$];
            return line;
        }
    }
    Adapter a = Adapter(example);
    parseInput(input, a);
}
