import core.bitop;
import std.algorithm;
import std.array;
import std.ascii;
import std.container;
import std.conv;
import std.math;
import std.numeric;
import std.range;
import std.stdio;
import std.string;
import std.typecons;
void log(A...)(A arg) { stderr.writeln(arg); }
int size(T)(in T s) { return cast(int)s.length; }

void main() {
    int N, M;
    int[][] B;
    bool input() {
        readf("%d %d\n", &N, &M);
        if (N == 0 && M == 0) return false;
        B = iota(0, N, 1).map!((i) => readln.chomp.map!((a) => cast(int)(a - '0')).array).array;
        return true;
    }
    void solve() {
        if (N <= M) {
            int ans = 0;
            foreach (int bit; 0 .. (1 << N)) {
                // bit: ????????¬??????????????????
                auto c = new int[M];
                foreach (i; 0 .. N) {
                    if (bit & (1 << i)) {
                        foreach (j; 0 .. M) {
                            c[j] += B[i][j];
                        }
                    }
                }
                if (c.all!((a) => a % 2 == 0)) {
                    ans = max(ans, bit.popcnt);
                }
            }
            writeln(ans);
        } else {
            auto X = B.map!((xs) => xs.map!(to!string).join("").to!int(2)).array;
            auto cur = new int[1 << M];
            auto prv = new int[1 << M];
            cur[] = int.min / 4;
            prv[] = int.min / 4;
            cur[0] = 0;
            foreach (j; 0 .. N) {
                swap(cur, prv);
                foreach (int bit; 0 .. (1 << M)) {
                    // bit: ????????????????????£??????
                    cur[bit ^ X[j]] = max(cur[bit ^ X[j]], prv[bit] + 1);
                    cur[bit] = max(cur[bit], prv[bit]);
                }
            }
            writeln(cur[0]);
        }
    }
    while (input()) {
        solve();
    }
}