Problem:
Score : 300 points

Problem Statement

We have a square grid with H rows and W columns.
Snuke wants to write 0 or 1 in each of the squares.
Here, all of the following conditions have to be satisfied:

For every row, the smaller of the following is A: the number of 0s contained in the row, and the number of 1s contained in the row. (If these two numbers are equal, “the smaller” should be read as “either”.)

For every column, the smaller of the following is B: the number of 0s contained in the column, and the number of 1s contained in the column.

Determine if these conditions can be satisfied by writing 0 or 1 in each of the squares. If the answer is yes, show one way to fill the squares so that the conditions are satisfied.

Constraints

1 \leq H,W \leq 1000

0 \leq A

2 \times A \leq W

0 \leq B

2 \times B \leq H

All values in input are integers.

Input

Input is given from Standard Input in the following format:

H W A B

Output

If the conditions cannot be satisfied by writing 0 or 1 in each of the squares, print -1.

If the conditions can be satisfied, print one way to fill the squares so that the conditions are satisfied, in the following format:

s_{11}s_{12}\cdots s_{1W}
s_{21}s_{22}\cdots s_{2W}
\vdots
s_{H1}s_{H2}\cdots s_{HW}

Here s_{ij} is the digit written in the square at the i-th row from the top and the j-th column from the left in the grid.

If multiple solutions exist, printing any of them will be accepted.

Sample Input 1

3 3 1 1

Sample Output 1

100
010
001

Every row contains two 0s and one 1, so the first condition is satisfied.
Also, every column contains two 0s and one 1, so the second condition is satisfied.

Sample Input 2

1 5 2 0

Sample Output 2

01010

Solution in C# (Mono 4.6.2.0) (judge verdict: Wrong Answer)

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;
using System.Globalization;
using System.Numerics;
using System.Text.RegularExpressions;
//byte 255 int<2147483647 ≒ 2 * 10^9 long < 9223372036854775807 ≒ 9 * 10^18
//decimal 29桁

class Myon
{
    //chokudaiさんのコードをコピペ
    static Scanner cin;
    public Myon() { }
    public static int Main()
    {
        //Console.SetOut(new Printer(Console.OpenStandardOutput()));
        cin = new Scanner();
        new Myon().calc();

        return 0;
    }

    public void calc()
    {
        int h = cin.nextInt();
        int w = cin.nextInt();
        int a = cin.nextInt();//行
        int b = cin.nextInt();

        //4 4 1 0
        //各行について、定まったaに対して1の数はa もしくは w-a個
        //すなわち、行列内の1の数N = a * h + k(w-2a)  (k=0 to h)
        //          min: a * h  max (w-a) * h  hは 0<1となる行の数
        //同様に N= b * w + k(h-2b) 
        //          min b * w   max (h-b) * w  hは 0<1となる列の数
        
        int h1, h2 = 0;
        for(h1 = 0; h1 <= h; h1++)
        {
            for(h2 = 0; h2 <= w; h2++)
            {
                int N1 = a * h + h1 * (w - 2 * a);
                int N2 = b * w + h2 * (h - 2 * b);
                if (N1 == N2) goto label;

            }
        }
        label:

        if (h1 > h || h2 > w) showL("No");
        else
        {
            showL($"h1:{h1} h2:{h2} N1:{a * h + h1 * (w - 2 * a)} N2:{b * w + h2 * (h - 2 * b)}");
            for(int i = 0; i < h; i++)
            {
                for(int j = 0; j < w; j++)
                {
                    if ((i < a ^ j < b)) show(1);
                    else show(0);

                }
                showL("");
            }

        }

    }

    public void calc_ABC076D()
    {
        int n = cin.nextInt();
        int[] t = new int[n + 1]; for (int i = 0; i < n; i++) t[i] = cin.nextInt();
        int[] v = new int[n + 1]; for (int i = 0; i < n; i++) v[i] = cin.nextInt();
        t[n] = 0; v[n] = 0;

        //k番目の拘束条件(t = Σti(i=0 ~ k-1) ~ Σti + tk) Σti(i=0 ~ k-1) を stk とかく
        //          (言い換えればk番目の拘束が始まる時間)
        //  は、言い換えればt = x において (v(x)を実際の速度として) 
        //  x <= stk-1 ⇒ v(x) <= vk + (stk-1 + x) 
        //  x >= stk ⇒ v(x) ∈ [vk - (stk - x), vk + (stk + x) ]

        int[] sumt = new int[n+2]; for (int i = 1; i < n + 2; i++) sumt[i] = sumt[i - 1] + t[i-1];
        int[] maxv = new int[sumt[n+1]+1];

        for(int tt = 1; tt < sumt[n+1]; tt++) 
        {
            maxv[tt] = maxv[tt - 1] + 1;
            for(int i = 0; i < n+1; i++)
            {
                if (tt <= sumt[i]) maxv[tt] = Math.Min(maxv[tt], v[i] + (sumt[i] - tt));
                else if( tt <= sumt[i] + t[i]) maxv[tt] = Math.Min(maxv[tt], v[i]);
            }
        }

        double ans = 0;
        int imadokonokousoku = 0;
        int tempt = 1;
        for (int tt = 1; tt < sumt[n]; tt++)
        {
            if(tempt == t[imadokonokousoku]) { tempt = 0; imadokonokousoku++; }
            ans += ((double)maxv[tt] + maxv[tt - 1]) / 2;
            if (maxv[tt] < v[imadokonokousoku] &&  maxv[tt] == maxv[tt + 1])
            {
                ans += 0.25;//t= a.5 に最大値がくる場合の補正
            }
            tempt++;
        }
        ans += 0.5;//最後の一秒 v = 1 to 0なので
        showL(ans);

    }
    public void calcC()
    {
        int n = cin.nextInt();

        //System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
        //sw.Start();

        int m = cin.nextInt();
        List<int> a = new List<int>(m);
        List<int> b = new List<int>(m);
        for (int i = 0; i < m; i++)
        {
            a.Add(cin.nextInt());
            b.Add(cin.nextInt());
        }

        int ans = 0;
        List<int> bridge = new List<int>();
        for(int i = 0; i < m; i++)
        {
            tempConnected = new bool[n];
            AddConnected(1, a, b, i);
            bool allconnected = true; for(int j = 0;j<n;j++) if (!tempConnected[j]) { allconnected = false;break; }
            if (!allconnected)
            {
                bridge.Add(i + 1);
                ans++;
            }
            //else
            //{
            //    showL($"{i + 1} is not bridge");
            //}
        }
        showL(ans);

        //sw.Stop();
        //showL($"処理時間: {sw.ElapsedMilliseconds} [msec]");


    }

    
    bool[] tempConnected;
    public void AddConnected(int index, List<int>a,List<int>b, int ignoreingBridge = -1)
    {
        //index番目のノードにつながるノードをconnectedにして、さらにaddconnectedを呼び出す
        for(int i = 0; i < a.Count; i++)
        {
            if (i == ignoreingBridge) continue;
            if (a[i] -1 == index && !tempConnected[b[i]-1]) { tempConnected[b[i]-1] = true; AddConnected(b[i]-1, a, b,ignoreingBridge); }
            else if (b[i]-1 == index && !tempConnected[a[i]-1]) { tempConnected[a[i]-1] = true; AddConnected(a[i]-1, a, b,ignoreingBridge); }
        }
   
    }
    public void backetSort(ref int[] a)
    {
        //max a << a.len に対して有効なソート
        //よってa = int[] とする
        long n = a.Length;
        var count = new int[n];
        var loc = new long[n];//loc[i] は i が終わる 位置 max index where c[index] = loc[i]
        for (long i = 0; i < n; i++) count[a[i]]++;
        loc[0] = count[0] - 1;
        for (long i = 0; i < n-1; i++) loc[i+1] = loc[i] + count[i+1]; 
        long index = 0;

        for(int i = 0; i < n; i++)
        {
            while (index <= loc[i]) a[index++] = i; //incex <= loc[i] == index < loc[i] + 1
        }
    }

    public static void showL<T>(T s) { Console.WriteLine(s); }
    public static void show<T>(T s) { Console.Write(s); }

}

class Printer : StreamWriter
{
    public override IFormatProvider FormatProvider { get { return CultureInfo.InvariantCulture; } }
    public Printer(Stream stream) : base(stream, new UTF8Encoding(false, true)) { }
    public Printer(Stream stream, Encoding encoding) : base(stream, encoding) { }
}

class Scanner
{
    string[] s;
    int i;

    char[] cs = new char[] { ' ' };

    public Scanner()
    {
        s = new string[0];
        i = 0;
    }

    public string next()
    {
        while (i >= s.Length)
        {
            string st = Console.ReadLine();
            while (st == "") st = Console.ReadLine();
            s = st.Split(cs, StringSplitOptions.RemoveEmptyEntries);
            i = 0;
        }
        return s[i++];
    }

    public int nextInt()
    {
        return int.Parse(next());
    }

    public int[] nextIntArr(long n)
    {
        int[] output = new int[n];
        for (int i = 0; i < n; i++) output[i] = nextInt();
        return output;
    }

    public long nextLong()
    {
        return long.Parse(next());
    }

    public double nextDouble()
    {
        return double.Parse(next());
    }

}

class SMath
{
    
    /// <summary>
    /// 素因数分解して、n番目に見つかった素因数をoutput[n-1]に返します。
    /// 12 なら 2,2,3 です。
    /// </summary>
    /// <param name="n"></param>
    /// <returns></returns>
    public static List<long> Factorization(long n)
    {
        if (n <= 0) return null;
        List<long> output = new List<long>();
        int i = 2;
        long max = (long)Math.Sqrt(n); ;
        while (n > 1)
        {
            if (i > max) { output.Add(n); break; }
            while (n % i == 0)
            {
                output.Add(i);
                n /= i;
            }
            i++;
        }
        return output;
    }

    /// <summary>
    /// 素因数分解して、n番目に見つかった素因数をoutput[n-1]に返します。
    /// 84 = (2^2 * 3 * 7) なら 2, 1, 0, 1 　remainder = 1です。(打ち切られない）
    /// 13 = 0,0,...0 remainder = 2019
    /// ただし、試行を打ち切った時に限り残りをremainderに返す。(remainderは素数または1となる)
    /// </summary>
    /// <param name="n"></param>
    /// <param name="remainder"></param>
    /// <returns></returns>
    public static List<long> Factorization(long n, out long remainder)
    {
        //output[i] が i-1番目の素数の数を示す
        //ただし、試行を打ち切った時に限り残りをremainderに返す。(remainderは素数または1となる)
        remainder = 1;
        if (n <= 0) return null;
        List<long> output = new List<long>();
        long tempn = 2;
        long max = (long)Math.Sqrt(n);
        bool[] isNOTPrime = new bool[max+1];
        while (n > 1)
        {

            if (tempn > max) { remainder = n; break; }
            if (!isNOTPrime[tempn])
            {
                output.Add(0);
                while (n % tempn == 0)
                {
                    output[output.Count - 1]++;
                    n /= tempn;
                }
                for (long j = tempn * 2; j < isNOTPrime.Length; j += tempn) isNOTPrime[j] = true;
            }
            tempn++;
        }
        return output;
    }

    /// <summary>
    /// i番目の素数をoutput[i-1]に返します。
    /// ただしnより大きい素数については判定しません。
    /// </summary>
    /// <param name="n"></param>
    /// <returns></returns>
    public static List<long> GetPrimeNumbers(long n)
    {
        if (n <= 0) return null;
        List<long> output = new List<long>();
        long tempn = 2;
        bool[] isNOTPrime = new bool[n + 1];
        while (n > 1)
        {
            if (tempn > n) { break; }
            if (!isNOTPrime[tempn])
            {
                output.Add(tempn);
                for (long j = tempn * 2; j < isNOTPrime.Length; j += tempn) isNOTPrime[j] = true;
            }
            tempn++;
        }
        return output;
    }


    private static long[][] combMemo;
    private static int maxn_combination = -1;
    public static long Combination(int n, int k)
    {
        if (n < 0 || k > n) return 0;
        if (n == k || k == 0) return 1;
        if (k > n/2) return Combination(n, n - k);
        if (maxn_combination < n)
        {
            maxn_combination = n;
            combMemo = new long[n+1][];
        }
        if (combMemo[n] == null) combMemo[n] = new long[n/2 + 1];
        if (combMemo[n][k] != 0) return combMemo[n][k];
        else
        {
            combMemo[n][k] = Combination(n - 1, k) + Combination(n - 1, k - 1);
            return combMemo[n][k];
        }
        
    }
    public static long Gcd(long a, long b)
    {
        if (a <= 0) return -1;
        //if (a > b) return gcd(b, a);
        if (b == 0) return a;
        return Gcd(b, a % b);
    }
    public static long Lcm(long a,long b)
    {
        return a / Gcd(a, b) * b;
    }
}