Problem:
Making Lunch Boxes
Taro has been hooked on making lunch boxes recently.
Taro has obtained a new lunch box recipe book today, and wants to try as many of the recipes listed in the book as possible.
Enough of the ingredients for all the recipes are at hand, but they all are in vacuum packs of two.
If only one of them is used leaving the other, the leftover will be rotten easily, but making two of the same recipe is not interesting.
Thus he decided to make a set of lunch boxes, each with different recipe, that wouldn't leave any unused ingredients.
Note that the book may include recipes for different lunch boxes made of the same set of ingredients.
How many lunch box recipes can Taro try today at most following his dogma?
Input
The input consists of at most 50 datasets, each in the following format.
n
m
b
1,1
...
b
1,
m
...
b
n,
1
...
b
n,m
The first line contains
n
, which is the number of recipes listed in the book, and
m
, which is the number of ingredients.
Both
n
and
m
are positive integers and satisfy 1 ≤
n
≤ 500, 1 ≤
m
≤ 500 and
1 ≤
n
×
m
≤ 500
.
The following
n
lines contain the information for each recipe with the string of length
m
consisting of 0 or 1.
b
i,j
implies whether the
i
-th recipe needs the
j
-th ingredient.
1 means the ingredient is needed for the recipe and 0 means not.
Each line contains at least one 1.
The end of the input is indicated by a line containing two zeros.
Output
For each dataset, output the maximum number of recipes Taro can try.
Sample Input
4 3
110
101
011
110
7 1
1
1
1
1
1
1
1
4 5
10000
01000
00100
00010
6 6
111111
011000
100000
000010
100001
100100
0 0
Output for the Sample Input
3
6
0
6

Submitted solutions:

code_snippet: #include<cstdio>
#include<iostream>
#include<map>
#include<vector>
#include<string>
#include<algorithm>

using namespace std;

string xx(string a, string b)
{
    for(int i = 0; i < a.size(); i++)
        a[i] = (a[i]-'0')^(b[i]-'0')+'0';
    return a;
}

int main()
{
    int n, m;
    while(cin >> n >> m && n != 0)
    {
        map<string, int> _m;
        vector<string> v(n);
        for(int i = 0; i < n; i++)
            cin >> v[i];
        for(int i = 0; i < v.size(); i++)
        {
            map<string, int> ma = _m;
            map<string, int>::iterator it = _m.begin();
            while(it != _m.end())
            {
                string tmp = xx(v[i], it->first);
                if(ma.count(tmp))
                {
                    ma[tmp] = max(it->second + 1, ma[tmp]);
                }
                else
                    ma[tmp] = it->second + 1;
                it++;
            }
            _m = ma;
            if(!_m.count(v[i]))
                _m[v[i]] = 1;
        }
        //for(map<string, int>::iterator it = ma.begin(); it != ma.end(); it++)
        string zero;
        for(int i = 0; i < m; i++)
            zero.push_back('0');
        if(_m.count(zero))
        {
            cout << _m[zero] << endl;
        }
        else
            cout << 0 << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 3790
memory_kb: 232696
final_rank: 16

code_snippet: #include<bits/stdc++.h>
//#include<atcoder/all>
using namespace std;
//using namespace atcoder;

using ll = long long;
using ld = long double;

//using mint = modint998244353;
//using mint = modint1000000007;

template<class T> using pq = priority_queue<T>; //大きい順
template<class T> using pq_g = priority_queue<T, vector<T>, greater<T>>; //小さい順

#define vec_unique(v) v.erase(unique(v.begin(), v.end()), v.end()) //重複削除
#define vec_iota(v) iota(v.begin(), v.end(), 0) //0, 1, 2, 3, ..., n - 1にセット

int dx[4] = {1, -1, 0, 0};
int dy[4] = {0, 0, 1, -1};
//int dx[8] = {1, 1, 0, -1, -1, -1, 0, 1};
//int dy[8] = {0, 1, 1, 1, 0, -1, -1, -1};

#define INF 2e18
#define INF2 2e9

int main() {
    while(true) {
        int n, m;
        cin >> n >> m;
        if(n == 0 && m == 0) {
            break;
        }

        vector<vector<char>> b(n, vector<char>(m));
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++) {
                cin >> b[i][j];
            }
        }

        if(n <= m) {
            int ans = 0;
            for(int i = 0; i < (1 << n); i++) {
                vector<int> ing(m);
                int cnt = 0;
                for(int j = 0; j < n; j++) {
                    if(i & (1 << j)) {
                        cnt++;
                        for(int k = 0; k < m; k++) {
                            if(b[j][k] == '1') {
                                ing[k]++;
                            }
                        }
                    }
                }
                bool flag = true;
                for(int k = 0; k < m; k++) {
                    if(ing[k] % 2 == 1) {
                        flag = false;
                    }
                }

                if(flag) {
                    ans = max(ans, cnt);
                }
            }

            cout << ans << endl;
        } else {
            vector<int> w(n);
            for(int i = 0; i < n; i++) {
                int d = 1;
                for(int j = m - 1; j >= 0; j--) {
                    if(b[i][j] == '1') w[i] += d;
                    d *= 2;
                }
            }

            vector<vector<int>> dp(n + 1, vector<int>((1 << m), -1));
            dp[0][0] = 0;
            for(int i = 0; i < n; i++) {
                for(int j = 0; j < (1 << m); j++) {
                    dp[i + 1][j] = dp[i][j];
                }
                for(int j = 0; j < (1 << m); j++) {
                    if(dp[i][j] != -1) dp[i + 1][j ^ w[i]] = max(dp[i + 1][j ^ w[i]], dp[i][j] + 1);
                }
            }

            cout << dp[n][0] << endl;
        }
    }
    //cout << fixed << setprecision(15) << << endl;
    return 0;
}
accuracy: 1
time_ms: 7190
memory_kb: 208672
final_rank: 20

code_snippet: #include <bits/stdc++.h>

using namespace std;

int n,m;
map<string,int>Table;

char now[505];

struct node
{
    string s;
    int x;

    //node(string s,int x):s(s),x(x){}
};

queue<node>q;

void dp()
{
    map<string,int>Temp;
    map<string,int>::iterator it;

    for (it=Table.begin();it!=Table.end();it++)
    {
        string old=it->first;
        string New="";
        for (int i=0;i<m;i++)
            if (now[i]==old[i]) New+="0";else New+="1";

        if (!Table.count(New))
        {
            node t;
            t.s=New;t.x=it->second+1;
            q.push(t);
        }
        else if (Table[New]<it->second+1)
        {
            Temp[New]=max(Temp[New],it->second+1);
            //cout<<old<<" "<<New<<" "<<Table[New]<<endl;
        }
    }

    while (!q.empty())
    {
        node temp=q.front();q.pop();
        Table[temp.s]=max(Table[temp.s],temp.x);
        //cout<<temp.s<<" "<<temp.x<<endl;
    }

    for (it=Temp.begin();it!=Temp.end();it++)
    {
        string s=it->first;
        Table[s]=Temp[s];
    }
}

int main()
{
    //ios_base::sync_with_stdio(false);
    //cin.tie(NULL); cout.tie(NULL);
    while (cin>>n>>m)
    {
        if (n==0 && m==0) break;

        string init="";
        for (int i=0;i<m;i++) init+="0";
        Table.clear();
        Table[init]=0;

        for (int i=0;i<n;i++)
        {
            //cin>>now;
            scanf("%s",now);
            dp();
        }

        printf("%d\n",Table[init]);
    }
    return 0;
}
accuracy: 1
time_ms: 5030
memory_kb: 120196
final_rank: 14

code_snippet: #include <bits/stdc++.h>

using namespace std;

int rp[505][505],n,m;
map<string,int>Table;
string now;

struct node
{
    string s;
    int x;

    //node(string s,int x):s(s),x(x){}
};

void dp()
{
    queue<node>q;
    map<string,int>Temp;

    map<string,int>::iterator it;
    for (it=Table.begin();it!=Table.end();it++)
    {
        string old=it->first;
        string New="";
        for (int i=0;i<m;i++)
            if (now[i]==old[i]) New+="0";else New+="1";

        if (!Table.count(New))
        {
            node t;
            t.s=New;t.x=it->second+1;
            q.push(t);
        }
        else if (Table[New]<it->second+1)
        {
            Temp[New]=max(Temp[New],it->second+1);
            //cout<<old<<" "<<New<<" "<<Table[New]<<endl;
        }
    }

    while (!q.empty())
    {
        node temp=q.front();q.pop();
        Table[temp.s]=max(Table[temp.s],temp.x);
        //cout<<temp.s<<" "<<temp.x<<endl;
    }

    for (it=Temp.begin();it!=Temp.end();it++)
    {
        string s=it->first;
        Table[s]=Temp[s];
    }
}

int main()
{
    //std::ios::sync_with_stdio(false);
    while (cin>>n>>m)
    {
        if (n==0 && m==0) break;

        string init="";
        for (int i=0;i<m;i++) init+="0";
        Table.clear();
        Table[init]=0;

        for (int i=0;i<n;i++)
        {
            cin>>now;
            dp();
        }

        cout<<Table[init]<<endl;
    }
    return 0;
}
accuracy: 1
time_ms: 4960
memory_kb: 120120
final_rank: 13

code_snippet: #include <bits/stdc++.h>

using namespace std;

int rp[505][505],n,m;
map<string,int>Table;

struct node
{
    string s;
    int x;

    node(string s,int x):s(s),x(x){}
};

void dp(string now)
{
    queue<node>q;
    map<string,int>Temp;
    for (map<string,int>::iterator it=Table.begin();it!=Table.end();it++)
    {
        string old=it->first;
        string New="";
        for (int i=0;i<m;i++)
            if (now[i]==old[i]) New+="0";else New+="1";

        if (!Table.count(New))
        {
            q.push(node(New,Table[old]+1));
        }
        else if (Table[New]<Table[old]+1)
        {
            Temp[New]=max(Temp[New],Table[old]+1);
            //cout<<old<<" "<<New<<" "<<Table[New]<<endl;
        }
    }

    while (!q.empty())
    {
        node temp=q.front();q.pop();
        Table[temp.s]=max(Table[temp.s],temp.x);
        //cout<<temp.s<<" "<<temp.x<<endl;
    }

    for (map<string,int>::iterator it=Temp.begin();it!=Temp.end();it++)
    {
        string s=it->first;
        Table[s]=Temp[s];
    }
}

int main()
{
    std::ios::sync_with_stdio(false);
    while (cin>>n>>m)
    {
        if (n==0 && m==0) break;

        string init="";
        for (int i=0;i<m;i++) init+="0";
        Table.clear();
        Table[init]=0;

        for (int i=0;i<n;i++)
        {
            string s;
            cin>>s;
            dp(s);
        }

        cout<<Table[init]<<endl;
    }
    return 0;
}
accuracy: 1
time_ms: 6180
memory_kb: 120204
final_rank: 15

code_snippet: #include <bits/stdc++.h>

using namespace std;

int rp[505][505],n,m;
map<string,int>Table;

struct node
{
    string s;
    int x;

    node(string s,int x):s(s),x(x){}
};

void dp(string now)
{
    queue<node>q;
    for (map<string,int>::iterator it=Table.begin();it!=Table.end();it++)
    {
        string old=it->first;
        string New="";
        for (int i=0;i<m;i++)
            if (now[i]==old[i]) New+="0";else New+="1";

        if (!Table.count(New))
        {
            q.push(node(New,Table[old]+1));
        }
        else if (Table[New]<Table[old]+1)
        {
            q.push(node(New,Table[old]+1));
            //cout<<old<<" "<<New<<" "<<Table[New]<<endl;
        }
    }

    while (!q.empty())
    {
        node temp=q.front();q.pop();
        Table[temp.s]=temp.x;
        //cout<<temp.s<<" "<<temp.x<<endl;

    }
}

int main()
{
    std::ios::sync_with_stdio(false);
    while (cin>>n>>m)
    {
        if (n==0 && m==0) break;

        string init="";
        for (int i=0;i<m;i++) init+="0";
        Table.clear();
        Table[init]=0;

        for (int i=0;i<n;i++)
        {
            string s;
            cin>>s;
            dp(s);
        }

        cout<<Table[init]<<endl;
    }
    return 0;
}
accuracy: 1
time_ms: 4530
memory_kb: 119508
final_rank: 12

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

int n, m;
char b[505][505];
int dp[1<<24], tmp[1<<24];
int tb[505];

bool input() {
    cin >> n >> m;
    if (!n && !m) return 0;
    for (int i = 0 ; i < n ; i++ ) {
        cin >> b[i];
    }
    return 1;
}

void solve() {
    int res = 0;
    memset(dp, -1, sizeof(dp));
    if ( n > m ) {
        memset(dp,-1,sizeof(dp));
        dp[0]=0;
        
        for (int i=0; i<n; i++){
            char *pEnd;
            int bb=strtol(b[i],&pEnd,2);
            for (int S=(1<<m)-1; S>=0; S--){
                if (dp[S^bb]!=-1)tmp[S] = dp[S^bb]+1;
                else tmp[S]=-1;
            }
            for (int S=(1<<m)-1; S>=0; S--){
                dp[S] = max(dp[S],tmp[S]);
            }
            res = dp[0];
        }
    } else { // n <= m
        for (int i = 1 ; i < (1<<n) ; i++ ) {
            int val = 0, cnt = 0;
            memset(tb, 0, sizeof(tb));
            for (int j = 0 ; j < n ; j++ ) {
                if ( i & (1 << j) ) {
                    for ( int k = 0 ; k < m ; k++ ) {
                        tb[k] ^= (b[j][k] - '0');
                    }
                    cnt++;
                }
            }
            bool flag = true;
            for ( int k = 0 ; k < m ;k++ ) {
                if ( tb[k] ) {
                    flag = false;
                    break;
                }
            }
            if ( flag ) {
                res = max(res, cnt);
            }
        }
    }
    cout << res << endl;
}

int main(){
    while(input()) {
        solve();
    }
}
accuracy: 1
time_ms: 5220
memory_kb: 79388
final_rank: 10

code_snippet: #include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<cstring>
using namespace std;

const int N = 500;

int a[N + 2][N + 2], n, m, st[(1 << 22) + 2], st2[(1 << 22) + 2], sum[N + 2], val[N + 2];

int main()
{
	for (; scanf("%d%d", &n, &m) && (n || m); )
	{
		for (int i = 0; i < n; i++)
			for (int j = 0; j < m; j++)
			{
				scanf("%1d", &a[i][j]);
			}
		int ans = 0;
		if (n <= 22)
		{
			for (int k = 1; k < 1 << n; k++)
			{
				for (int i = 0; i < m; i++)
					sum[i] = 0;
				int cnt = 0;
				for (int l = 0; l < n; l++)
					if (k >> l & 1)
					{
						cnt++;
						for (int i = 0; i < m; i++)
							sum[i] ^= a[l][i];
					}
				int ok = 1;
				for (int i = 0; i < m; i++)
					if (sum[i])
						ok = 0;
				if (ok)
					ans = max(ans, cnt);
			}
		}
		else
		{
			for (int i = 0; i < 1 << m; i++)
				st[i] = st2[i] = 0;
			for (int i = 0; i < n; i++)
			{
				val[i] = 0;
				for (int j = 0; j < m; j++)
				{
					val[i] = 2 * val[i] + a[i][j];
				}
			}
			for (int i = 0; i < n; i++)
			{
				if (st[val[i]] > 0)
					ans = max(ans, st[val[i]] + 1);
				for (int j = 0; j < 1 << m; j++)
					st2[j^val[i]] = st[j] > 0 ? st[j] + 1 : 0;
				st2[val[i]] = max(st2[val[i]], 1);
				for (int j = 0; j < 1 << m; j++)
					st[j] = max(st[j], st2[j]);
			}
		}
		printf("%d\n", ans);
	}
}

/*


*/
accuracy: 1
time_ms: 5310
memory_kb: 24384
final_rank: 8

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

map < unsigned long long , int > dp[505];
bitset < 505 > a[505];
int n,m;
char s[505];
hash < bitset < 505 > > H;

int dfs( int pos, bitset < 505 > s ){
	if ( pos == n ){
		if ( s.count() == 0 ) return 0;
		else return -1e9;
	}
	
	hash < bitset < 505 > > H;
	if ( dp[pos].find(H(s)) != dp[pos].end() ) return dp[pos][H(s)];
	int ans = dfs(pos+1,s);
	ans = max( ans, dfs(pos+1, s ^ a[pos]) + 1);
	return dp[pos][H(s)] = ans;
}

int main(){
	
	while ( scanf("%d%d",&n,&m) == 2 && n + m > 0 ){
		for ( int i = 0; i < n; i++ ){
			a[i].reset();
			scanf("%s",&s);
			int len = strlen(s);
			for ( int j = 0; j < m; j++ ){
				if ( s[j] == '0' ) continue;
				a[i].set(j);
			}
			dp[i].clear();
		}
		
		bitset < 505 > bs;
		printf("%d\n",dfs(0,bs));
	}
	return 0;
}
accuracy: 1
time_ms: 6480
memory_kb: 153228
final_rank: 17

code_snippet: #include <bits/stdc++.h>
#include <atcoder/all>
using namespace std;
using namespace atcoder;

using ll = long long;
const int MOD = 1000000007;
const int Mod = 998244353;
const int MAX = 1000000005;
const long long INF = 1000000000000000005LL;
#define rep(i, n) for (int i = 0; i < (n); i++)
#define rep2(i, a, b) for (int i = (a); i < (b); i++)
#define rrep(i, n) for (int i = (n) - 1; i >= 0; i--)
#define all(x) (x).begin(),(x).end()
template<class T>bool chmax(T& a, const T& b) { if (a < b) { a = b; return 1; } return 0; }
template<class T>bool chmin(T& a, const T& b) { if (b < a) { a = b; return 1; } return 0; }

bool solve() {
    int n, m;
    cin >> n >> m;
    if (n == 0 && m == 0) return false;
    vector<string> b(n);
    for (int i = 0; i < n; i++) cin >> b[i];
    int ans = 0;
    if (n <= 22) {
        vector<int> s(m);
        for (int bit = 0; bit < (1 << n); bit++) {
            for (int i = 0; i < n; i++) {
                if (bit & (1 << i)) {
                    for (int j = 0; j < m; j++) s[j] ^= (int)(b[i][j] - '0');
                }
            }
            bool ok = true;
            for (int i = 0; i < m; i++) {
                if (s[i]) {
                    ok = false;
                    s[i] = 0;
                }
            }
            if (ok) ans = max(ans, __builtin_popcount(bit));
        }
    } else {
        vector<vector<int>> dp(n+1, vector<int>(1 << m, -1));
        dp[0][0] = 0;
        for (int i = 0; i < n; i++) {
            int binary = 0;
            for (int j = 0; j < m; j++) binary += (int)(b[i][j] - '0') * (1 << j);
            for (int bit = 0; bit < (1 << m); bit++) {
                dp[i+1][bit] = max(dp[i+1][bit], dp[i][bit]);
                if (dp[i][bit] != -1) {
                    int nxtbit = bit ^ binary;
                    dp[i+1][nxtbit] = max(dp[i+1][nxtbit], dp[i][bit] + 1);
                }
            }
        }
        ans = dp[n][0];
    }
    cout << ans << endl;
    return true;
}

int main() {
    while (solve()) {}
}
accuracy: 1
time_ms: 6350
memory_kb: 208976
final_rank: 19

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

bool solve(){
    int n,m;cin>>n>>m;
    if(n==0)return 0;
    vector<string>b(n);
    for(auto &x:b)cin>>x;

    int ans=0;
    if(n<m){
        for(int s=0;s<(1<<n);s++){
            vector<int>c(m);
            int pc=0;
            for(int i=0;i<n;i++){
                if(s>>i&1){
                    pc++;
                    for(int j=0;j<m;j++)c[j]^=(b[i][j]-'0');
                }
            }
            bool ng=false;
            for(int j=0;j<m;j++)if(c[j])ng=true;
            if(!ng)ans=max(ans,pc);
        }
    }else{
        vector<int>dp(1<<m,-1e6);
        dp[0]=0;
        //使用材料xorがsのときのmax
        vector<int>c(n);
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++)c[i]=c[i]*2+int(b[i][j]-'0');
        }
        for(int i=0;i<n;i++){
            vector<int>old(1<<m,-1e6);
            swap(old,dp);
            for(int s=0;s<(1<<m);s++){
                dp[s]=max(dp[s],old[s]);
                dp[s^c[i]]=max(dp[s^c[i]],old[s]+1);
            }
        }        
        ans=dp[0];
    }
    cout<<ans<<endl;
    return 1;
}
int main(){
    while(solve());
    return 0;
}
accuracy: 1
time_ms: 2960
memory_kb: 36356
final_rank: 3

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

bool solve(){
    int n,m;cin>>n>>m;
    if(n==0)return 0;
    vector<string>b(n);
    for(auto &x:b)cin>>x;

    int ans=0;
    if(n<m){
        for(int s=0;s<(1<<n);s++){
            vector<int>c(m);
            int pc=0;
            for(int i=0;i<n;i++){
                if(s>>i&1){
                    pc++;
                    for(int j=0;j<m;j++)c[j]^=(b[i][j]-'0');
                }
            }
            bool ng=false;
            for(int j=0;j<m;j++)if(c[j])ng=true;
            if(!ng)ans=max(ans,pc);
        }
    }else{
        vector<int>dp(1<<m,-1e6);
        dp[0]=0;
        //使用材料xorがsのときのmax
        vector<int>c(n);
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++)c[i]=c[i]*2+int(b[i][j]-'0');
        }
        for(int i=0;i<n;i++){
            vector<int>old(1<<m,-1e6);
            swap(old,dp);
            for(int s=0;s<(1<<m);s++){
                dp[s]=max(dp[s],old[s]);
                dp[s^c[i]]=max(dp[s^c[i]],old[s]+1);
            }
        }        
        ans=dp[0];
    }
    cout<<ans<<endl;
    return 1;
}
int main(){
    while(solve());

    return 0;
}
accuracy: 1
time_ms: 2960
memory_kb: 36412
final_rank: 4

code_snippet: #pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;

// 数値型
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using P = pair<int,int>;
using Pll = pair<ll, ll>;
using Pli = pair<ll, int>;
using Pil = pair<int, ll>;

// vector関連
using vi = vector<int>;
using vvi = vector<vi>;
using vvvi = vector<vvi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using vvvll = vector<vvll>;
template<typename T>
using vc = vector<T>;
template<typename T>
using vvc = vector<vc<T>>;
template<typename T>
using vvvc = vector<vvc<T>>;
template<typename T>
using vvvvc = vector<vvvc<T>>;

// priority_queue
template<typename T>
using pq = priority_queue<T>;
template<typename T>
using pqg = priority_queue<T, vc<T>, greater<T>>;

#define rep(i, n) for(int i = 0; i < (int)(n); i++)
#define FOR(i, a, b) for(int i = a; i < (int)(b); i++)
#define all(a) (a).begin(),(a).end()
#define rall(a) (a).rbegin(),(a).rend()
#define MIN(vec) *min_element(vec)
#define MAX(vec) *max_element(vec)
#define next_perm(vec) (vec).begin(), (vec).end()
#define UNIQUE(vec) vec.erase(unique(vec.begin(), vec.end()), vec.end())
#define el "\n"
#define Yes cout << "Yes" << el
#define No cout << "No" << el
#define YES cout << "YES" << el
#define NO cout << "NO" << el
#define EPS 1e-8
#define Equal(a, b) (fabs((a)-(b)) < EPS) 
#define dbg(x) cerr << #x << "=" << x << el 

// 定数
const string abc = "abcdefghijklmnopqrstuvwxyz";
const string ABC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
constexpr int INF = 1001001001;
constexpr ll LINF = 1001001001001001001ll;
constexpr int DX[] = {1, 0, -1, 0};
constexpr int DY[] = {0, 1, 0, -1};
constexpr int DX8[] = {1, 0, -1, 0, 1, 1, -1, -1};
constexpr int DY8[] = {0, 1, 0, -1, 1, -1, 1, -1};

template<typename T1, typename T2>
ostream &operator<< (ostream &os, pair<T1, T2> p) {
    os << "{" << p.first << "," << p.second << "}";
    return os;
}
template<typename T>
ostream &operator<< (ostream &os, vc<T> &vec) {
    int sz = vec.size();
    rep(i, sz){
        os << vec[i] << (i==sz-1?"":" ");
    }
    return os;
}

template<typename T1, typename T2>
istream &operator>> (istream &is, pair<T1, T2> &p) {
    is >> p.first >> p.second;
    return is;
}
template<typename T>
istream &operator>> (istream &is, vc<T> &vec) {
    int sz = vec.size();
    rep(i, sz) { is >> vec[i]; }
    return is;
}
/// @brief aとｂの最大値をaに格納。更新があったかbool値を返す
/// @tparam T1 
/// @tparam T2 
/// @param a 
/// @param b 
/// @return bool
template<typename T1, typename T2>
inline bool chmax(T1 &a, T2 b){
    bool ret = a<b;
    if(ret) a = b;
    return ret;
}

/// @brief aとｂの最小値をaに格納。更新があったかbool値を返す
/// @tparam T1 
/// @tparam T2 
/// @param a 
/// @param b 
/// @return bool
template<typename T1, typename T2>
inline bool chmin(T1 &a, T2 b){
    bool ret = a>b;
    if(ret) {a = b;}
    return ret;
}

inline void YesNo(bool flag){
    if(flag) {Yes;}
    else {No;}
    return;
}

inline void YESNO(bool flag){
    if(flag) {YES;}
    else {NO;}
    return;
}

inline bool outof(ll x, ll xlim){
    return (x<0 || x>=xlim);
}

template<typename T>
inline T sqnorm(T x, T y){
    return x*x+y*y;
}

/// @brief char->int
/// @param c 
/// @return int
inline int ctoi(char c){
    return c-'0';
}

/// @brief xを素因数分解
/// @param x 
/// @return vector<Pli>, 素因数の昇順に {p, cnt}
vector<Pli> prime_fact(ll x){
    vector<Pli> ret;
    for(ll i=2; i*i<=x; i++){
        if(x%i == 0){
            ret.emplace_back(i, 0);
            while(x%i == 0){
                ret.back().second++;
                x /= i;
            }
        }
    }
    if(x != 1) ret.emplace_back(x, 1);
    return ret;
}

/// @brief xの約数列挙
/// @param x 
/// @return vll, 約数の昇順
vll divisor_enum(ll x){
    vector<ll> ret;
    for(ll i=1; i*i<=x; i++){
        if(x%i == 0){
            ret.push_back(x/i);
            ret.push_back(i);
        }
    }
    sort(all(ret));
    UNIQUE(ret);
    return ret;
}

/// @brief 繰り返し二乗法。
/// @tparam T 
/// @param x 
/// @param k 
/// @param op 
/// @param e 
/// @return 
template<typename T>
T pow_t(T x, ll k, T (*op)(T, T), T (*e)()){
    T ret = e();
    while(k){
        if(k&1) ret *= x;
        x *= x;
        k >>= 1;
    }
    return ret;
}

ll powll(ll x, ll k){
    return pow_t<ll>(x, k, [](ll a, ll b) -> ll{return a*b;}, []() -> ll{return 1;});
}

inline int pop_cnt(ll x) { return __builtin_popcountll(x); }
inline int top_bit(ll x) { return (x==0?-1:63-__builtin_clzll(x));}

void main2();

int main(){
    ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    main2();
}

bool solve2(int n, int m){
    if(n == 0) return false;
    vc<string> b(n);
    rep(i, n) cin >> b[i];
    vc<bitset<500>> b2(n, bitset<500>(0));
    rep(i, n){
        rep(j, m){
            if(b[i][j] == '1') b2[i].set(j, 1);
        }      
    }
    int ans = 0;
    rep(S, 1<<n){
        bitset<500> bs(0);
        int cnt = pop_cnt(S);
        if(cnt <= ans) continue; 
        rep(j, n){
            if(S>>j&1) bs ^= b2[j];
        }
        if(bs.count() == 0) ans = cnt;
    }
    cout << ans << el;
    return true;
}
bool solve3(int n, int m){
    vc<string> b(n);
    rep(i, n) cin >> b[i];
    vi dp(1<<m, -INF);
    vi dp2(1<<m, -INF);
    dp[0] = 0;
    rep(i, n){
        int mask = 0;
        rep(j, m) if(b[i][j] == '1') mask |= 1<<j;
        rep(S, 1<<m){
            dp2[S] = max(dp[S], dp[S^mask]+1);            
        }
        swap(dp, dp2);
    }
    cout << dp[0] << el;
    return true;
}
bool solve(){
    int n, m;
    cin >> n >> m;
    if(n == 0) return false;
    if(n < m){
        return solve2(n, m);
    }
    else{
        return solve3(n, m);
    }
}

void main2(){
    while(solve()){
        ;
    }
}
accuracy: 1
time_ms: 710
memory_kb: 36212
final_rank: 2

code_snippet: #pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")

// #ifndef ONLINE_JUDGE
// #define _GLIBCXX_DEBUG // 配列外参照のエラー
// #endif

// スタンダードライブラリ
#include <bits/stdc++.h>
using namespace std;

// 型関連
using ll = long long;
using lint = long long;
using pll = pair<ll, ll>;
using plll = tuple<ll, ll, ll>;
using pii = pair<int, int>;
using piii = tuple<ll, ll, ll>;
template <class T> using prique = priority_queue<T>;

// 型定数
constexpr ll mod = 998244353;
constexpr ll MOD = 1000000007;
int INF32 = 2e9;
ll INF64 = 9e18;
#define endl '\n';

int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};

/////////////////////////// print関連
template <typename T> void print(vector<T> A);
void print();
template <class Head, class... Tail> void print(Head &&head, Tail &&...tail);
void print(string S);
template <typename T> void print(vector<vector<T>> &F);

inline void Yes(bool f);

///////////////////ここから//////////////////////
bool solve() {
    int N, M;
    cin >> N >> M;
    if (N == 0) {
        return false;
    }
    vector<string> SS;
    vector<int> B(N);
    for (int i = 0; i < N; i++) {
        string S;
        cin >> S;
        SS.push_back(S);
        int val = 0;
        for (int j = 0; j < M; j++) {
            if (S[j] == '1') {
                val += (1 << j);
            }
        }
        B[i] = val;
    }
    if (N <= 22) {
        int ans = 0;
        for (int S = 0; S < (1 << N); S++) {
            int cnt = 0;
            vector<int> V(M);
            for (int i = 0; i < N; i++) {
                if (S & (1 << i)) {
                    cnt++;
                    for (int j = 0; j < M; j++) {
                        if (SS[i][j] == '1') {
                            V[j]=1-V[j];
                        }
                    }
                }
            }
            bool ok = true;
            for (int j = 0; j < M; j++) {
                if (V[j]) {
                    ok = false;
                    break;
                }
            }
            if (ok) {
                ans=max(ans,cnt);
            }
        }
        print(ans);
    } else {
        vector<int> dp(1 << M, -1);
        dp[0] = 0;
        for (int i = 0; i < N; i++) {
            vector<int> ndp(1 << M, -1);
            for (int S = 0; S < (1 << M); S++) {
                if (dp[S] == -1) {
                    continue;
                }
                ndp[S ^ B[i]] = max(ndp[S ^ B[i]], dp[S] + 1);
                ndp[S] = max(ndp[S], dp[S]);
            }
            swap(dp,ndp);
        }
        print(dp[0]);
    }

    return true;
}

int main() {
    ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    while (solve())
        ;
}

////////////////////print/////////////////////////
// 1次元ベクトルを出力する
template <typename T> void print(vector<T> A) {
    if (A.size() == 0) {
        return;
    }
    for (size_t i = 0; i < A.size() - 1; i++) {
        cout << A[i] << ' ';
    }
    cout << A[A.size() - 1] << endl;
    return;
}

// 2次元ベクトルを出力する
template <typename T> void print(vector<vector<T>> &F) {
    for (size_t i = 0; i < F.size(); i++) {
        for (size_t j = 0; j < F[i].size(); j++) {
            cout << F[i][j];
            if (j < F[i].size() - 1) {
                cout << ' ';
            }
        }
        cout << endl;
    }
}

// 空白行を出力するprint
void print() { cout << endl; }

// 数値・文字列を空白区切りで出力する. print(a,b)など
template <class Head, class... Tail> void print(Head &&head, Tail &&...tail) {
    cout << head;
    if (sizeof...(tail) != 0)
        cout << " ";
    print(forward<Tail>(tail)...);
}

void print(string S) { cout << S << endl; }

//////////////出力関連

inline void Yes(bool f) {
    if (f) {
        cout << "Yes" << endl;
    } else {
        cout << "No" << endl;
    }
}
accuracy: 1
time_ms: 4000
memory_kb: 19832
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define ll long long

vector<int> myxor(vector<int> &a,vector<int> &b){
  assert(a.size()==b.size());
  vector<int> ans(a.size(),0);
  for(int i=0;i<(ll)a.size();i++){
    ans.at(i)=a.at(i)^b.at(i);
  }
  return ans;
}

bool solve(){
  int n,m; cin>>n>>m;
  if(n==0 && m == 0) return 0;

  vector<vector<int>> b(n,vector<int>(m));
  vector<ll> recipeint(n,0);

  for(int i=0;i<n;i++){
    for(int j=0;j<m;j++){
      char c; cin>>c;
      b[i][j] = c-'0';
    }
  }
  ll ans=0;
  if(n <= 20){
    for(int i=0;i<(1<<n);i++){
      bitset<501> bt(0);
      ll siz=0;
      for(int k=0;k<n;k++){
        if(i&(1<<k)){
          siz++;
          for(int j=0;j<m;j++){
            if(b[k][j]==1)bt.flip(j);
          }
        }
      }
      if((int)bt.count()!=0)continue;
      ans=max(ans,siz);
    }
  }
  else{
    map<vector<int>,ll> mp;
    vector<pair<vector<int>,ll>> t(0);
    for(int i=0;i<n;i++){
      t.clear();
      if(mp.count(b.at(i))==0){
        t.push_back(make_pair(b.at(i),1));
      }
      for(pair<vector<int>,ll> pp:mp){
        t.push_back(make_pair(myxor(pp.first,b.at(i)),pp.second+1));
      }
      for(int i=0;i<(ll)t.size();i++){
        if(mp.count(t.at(i).first)==0){
          mp[t.at(i).first]=t.at(i).second;
        }
        else{
          mp.at(t.at(i).first)=max(mp.at(t.at(i).first),t.at(i).second);
        }
      }
    }
    if(mp.count(vector<int>(m,0))==0){
      ans=0;
    }
    else{
      ans=mp.at(vector<int>(m,0));
    }
  }
  cout<<ans<<endl;
  return 1;
}

int main(){
  while(solve());
}
accuracy: 1
time_ms: 4070
memory_kb: 249200
final_rank: 18

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

#pragma GCC optimize("Ofast")

#define rep(i, n) for(ll i = 0; i < (n); ++i)
#define all(A) A.begin(), A.end()

bool chmin(auto &a, auto b) {return a > b ? a = b, 1 : 0;}
bool chmax(auto &a, auto b) {return a < b ? a = b, 1 : 0;}

using ll = long long;

void print(auto... vs) {
  ((cout << vs << ' '), ...) << endl;
}

struct dsu {
  int n;
  vector<int> par;

  dsu(int n) : n(n), par(n, -1){};

  int find(int v) {
    if(par[v] < 0) return v;
    return par[v] = find(par[v]);
  }

  bool merge(int x, int y) {
    x = find(x);
    y = find(y);
    if(x == y) return false;
    if(par[x] > par[y]) swap(x, y);
    par[x] += par[y];
    par[y] = x;
    return true;
  }

  int size(int v) { return -par[find(v)]; }

  bool same(int x, int y) { return find(x) == find(y); }
};

int main() {
  while(1) {
    ll N, M; cin >> N >> M;
    if(N + M == 0) break;
    vector<string> B(N);
    rep(i, N) {
      cin >> B[i];
    }
    
    ll res = 0;
    if(N <= 26) {
      // N < 25
      using bs = bitset<500>;
      vector<bs> b(N);
      rep(i, N) {
        b[i] = 0;
        rep(j, M) {
          if(B[i][j] == '1') b[i][j] = 1;
        }
      }
      // rep(i, N) {
      //   print(b[i]);
      // }
      
      for(ll bit = 0; bit < (1LL<<N); ++bit) {
        bs tmp = 0;
        rep(i, N) {
          if(bit & (1LL<<i)) {
            tmp ^= b[i];
          }
        }
        // print(bit, tmp);
        if(tmp == 0) chmax(res, __builtin_popcountll(bit));
      }
      
      
    }
    else {
      // M < 25
      vector<int> b(N);
      rep(i, N) {
        ll now = 0;
        rep(j, M) {
          now *= 2;
          now += (B[i][j] - '0');
        }
        b[i] = now;
      }
      
      vector dp(N+1, vector<int>(1LL<<M, -1));
      dp[0][0] = 0;
      rep(i, N) {
        rep(bit, 1LL<<M) {
          if(dp[i][bit] >= 0) {
            chmax(dp[i+1][bit], dp[i][bit]);
            chmax(dp[i+1][bit ^ b[i]], dp[i][bit] + 1);
          }
        }
      }
      
      // rep(i, N) {
      //   rep(bit, 1LL<<M) {
      //     print(i, bit, dp[i][bit]);
      //   }
      // }
      res = max(dp[N][0], 0);
    }
    
    cout << res << endl;
    
  }
  
  return 0;
}
accuracy: 1
time_ms: 5800
memory_kb: 33256
final_rank: 9

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

void solve1(int N, int M, vector<string> B) {
    vector<bitset<500>> bit(N);
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            if (B[i][j] == '1') bit[i].set(j);
        }
    }
    int ans = 0;
    for (int i = 0; i < 1 << N; i++) {
        bitset<500> b;
        for (int j = 0; j < N; j++) {
            if (i >> j & 1) b ^= bit[j];
        }
        if (b.count() == 0) {
            ans = max(ans, __builtin_popcount(i));
        }
    }
    cout << ans << '\n';
}

void solve2(int N, int M, vector<string> B) {
    vector<int> dp(1 << M, -1 << 30);
    dp[0] = 0;
    for (int i = 0; i < N; i++) {
        auto ep = dp;
        int bit = 0;
        for (int j = 0; j < M; j++) {
            if (B[i][j] == '1') bit ^= 1 << j;
        }
        for (int j = 0; j < 1 << M; j++) {
            ep[j ^ bit] = max(ep[j ^ bit], dp[j] + 1);
        }
        dp = ep;
    }
    cout << dp[0] << '\n';
}

bool solve() {
    int N, M;
    cin >> N >> M;
    if (N == 0 && M == 0) return false;
    vector<string> B(N);
    for (int i = 0; i < N; i++) cin >> B[i];
    if (N <= 23) solve1(N, M, B);
    else solve2(N, M, B);
    return true;
}

int main() {
    while (solve()) {}
}
accuracy: 1
time_ms: 4710
memory_kb: 12516
final_rank: 7

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

#include <atcoder/all>
using namespace atcoder;

using ll = long long;
using mint = modint998244353;

unordered_map<string, int> enumerate(vector<string> S, int M) {
    int N = S.size();
    unordered_map<string, int> ret;
    for(int s = 0; s < 1 << N; s++) {
        int cnt = 0;
        string x(M, '0');
        for(int i = 0; i < N; i++) {
            if((~s >> i) & 1) continue;
            cnt++;
            for(int j = 0; j < M; j++) {
                x[j] ^= S[i][j] - '0';
            }
        }
        ret[x] = max(ret[x], cnt);
    }
    return ret;
}

bool solve() {
    int N, M;
    cin >> N >> M;
    if(N == 0) return false;
    vector<string> S(N);
    for(int i = 0; i < N; i++) {
        cin >> S[i];
    }
    if(N <= 30) {
        vector<string> L, R;
        for(int i = 0; i < N; i++) {
            (i & 1 ? L : R).push_back(S[i]);
        }
        auto mpl = enumerate(L, M);
        auto mpr = enumerate(R, M);
        int ans = 0;
        for(auto [s, c] : mpl) {
            if(mpr.count(s)) ans = max(ans, c + mpr[s]);
            // cout << s << " " << c << " " << (mpr.count(s) ? mpr[s] : 0) << endl;
        }
        cout << ans << endl;
    }else {
        vector<int> A;
        for(auto s : S) {
            int ret = 0;
            for(char c : s) ret = 2 * ret + (c - '0');
            A.push_back(ret);
        }
        const int INF = 1 << 20;
        vector dp(N + 1, vector<int>(1 << M, -INF));
        dp[0][0] = 0;
        for(int i = 0; i < N; i++) {
            for(int j = 0; j < 1 << M; j++) {
                dp[i + 1][j] = max(dp[i + 1][j], dp[i][j]);
                dp[i + 1][j ^ A[i]] = max(dp[i + 1][j ^ A[i]], dp[i][j] + 1);
            }
        }
        cout << dp[N][0] << endl;
    }
    return true;
}

int main() {
    while(solve());
}
accuracy: 1
time_ms: 20
memory_kb: 12740
final_rank: 1

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

using ll =long long;

using BS=bitset<500>;
void solve(ll H,ll W){
    vector<BS> B(H);
    for(int i=0;i<H;i++){
        string S;
        cin>>S;
        B[i]=BS(S);
    }
    unordered_map<BS,ll> M;
    M[0]=0;
    for(int i=0;i<H;i++){
        unordered_map<BS,ll> NM;
        for(auto [m,n]:M){
            NM[m]=max(NM[m],n);
            NM[m^B[i]]=max(NM[m^B[i]],n+1);
        }
        swap(NM,M);
    }
    cout<<M[0]<<endl;

    
}


int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    ll H,W;
    while(cin>>H>>W,H+W!=0)
    solve(H,W);
}
accuracy: 1
time_ms: 2990
memory_kb: 167704
final_rank: 11

code_snippet: #include <bits/stdc++.h>
#include <unordered_map>
#include <stdlib.h>
using namespace std;
#define rep(i, a, n) for(ll i = a; i < n; i++)
#define rrep(i, a, n) for(ll i = a; i >= n; i--)
#define ll long long
#define pii pair<int, int>
#define pll pair<ll, ll>
#define all(x) (x).begin(), (x).end()
//constexpr ll MOD = 1000000007;
constexpr ll MOD = 998244353;
constexpr int IINF = 1001001001;
constexpr ll INF = 1LL<<60;
template<class t,class u> void chmax(t&a,u b){if(a<b)a=b;}
template<class t,class u> void chmin(t&a,u b){if(b<a)a=b;}


ll gcd(ll a, ll b){
    if(a%b == 0){
      return b;
    }else{
      return gcd(b, a%b);
    }
}

ll lcm(ll a, ll b){
    return a*b / gcd(a, b);
}

ll powMod(ll x, ll n) {
    if (n == 0) return 1 % MOD;
    ll val = powMod(x, n / 2);
    val *= val;
    val %= MOD;
    if (n % 2 == 1) val *= x;
    return val % MOD;
}

int main() {
    while(true){
        ll n, m; cin >> n >> m;
        if(n*m == 0) break;
        if(n < m){
            vector<vector<ll>> b(n,vector<ll>(m));
            rep(i,0,n){
                string s; cin >> s;
                rep(j,0,m) b[i][j] = s[j]-'0';
            }
            ll ans = 0;
            // rep(i,0,n){
            //     rep(j,0,m) cout << b[i][j];
            //     cout << endl;
            // }
            rep(bit,0,1LL<<n){
                vector<ll> num(m,0);
                rep(i,0,n){
                    if(bit>>i&1){
                        rep(j,0,m) num[j] ^= b[i][j];
                    }
                }
                ll sum = 0;
                rep(j,0,m) sum += num[j];
                if(sum == 0){
                    chmax(ans, __popcount(bit));
                    // cout << "bit:" << bit << endl;
                }
            }
            cout << ans << endl;
        }else{
            vector<ll> b(n);
            rep(i,0,n){
                string s; cin >> s;
                ll num = 0;
                for(auto c: s){
                    num *= 2;
                    num += c-'0';
                }
                b[i] = num;
            }
            vector<ll> dp(1LL<<m, -INF);
            dp[0] = 0;
            rep(i,0,n){
                vector<ll> ndp(1LL << m, -INF);
                rep(j,0,1LL<<m){
                    if(dp[j] == -INF) continue;
                    chmax(ndp[j], dp[j]);
                    chmax(ndp[j^b[i]], dp[j]+1);
                }
                swap(dp, ndp);
            }
            cout << dp[0] << endl;
        }
    }
    return 0;
}
accuracy: 1
time_ms: 2740
memory_kb: 73064
final_rank: 6