// Slower C++ solution:
#include <algorithm>

#include <cstring>

#include <map>

#include <iostream>



using namespace std;



bool maps[12][10002];

bool row[12];

int ans=0x7fffffff;

int r,c;

int r_c;

map<string,bool>prow;



int dfs(int st)

{

    for(int i=st;i<r;++i)

    {

        if(row[i])continue;

        else

        {

            row[i]=true;

            string str1="0000000000",str2="0000000000";

            for(int j=0;j<r;++j)

            {

                str1[j]=row[j]+'0';

                str2[j]=!row[j]+'0';

            }

            if(prow.count(str1)||prow.count(str2));

            else

            {

                prow[str1]=true;

                prow[str2]=true;

                int sun=0;

                for(int j=0;j<c;++j)

                {

                    int s=0;

                    for(int k=0;k<r;++k)

                        s+=(maps[k][j]^row[k]);

                    sun+=min(s,r-s);

                    if(sun>ans)break;

                }

                ans=min(ans,sun);

            }

            dfs(st+1);

            row[i]=false;

        }

    }

    return 0;

}



int main()

{

    while(scanf("%d%d",&r,&c),r+c)

    {

        r_c=r*c;

        prow.clear();

        memset(maps,0,sizeof(maps));

        memset(row,0,sizeof(row));

        ans=0x7fffffff;

        for(int i=0;i<r;++i)

            for(int j=0;j<c;++j)

                scanf("%d",&maps[i][j]);

        dfs(0);

        printf("%d\n",r_c-ans);

    }

    return 0;

}


// Faster C++ solution for the same problem (measured speedup: 1.1496665698114796x):
// {{{ by unolight

#include <bits/stdc++.h>

#include <unistd.h>

#pragma GCC diagnostic ignored "-Wunused-result"

#define SZ(x) ((int)(x).size())

#define ALL(x) begin(x),end(x)

#define RALL(x) rbegin(x),rend(x)

#define REP(i,n) for ( int i=0; i<int(n); i++ )

#define REP1(i,a,b) for ( int i=(a); i<=int(b); i++ )

#define MP make_pair

#define PB push_back

using namespace std;

typedef int64_t LL;

typedef pair<int,int> PII;

template<class T> using V = vector<T>;

template<class T> using VV = vector<vector<T>>;



template<class T> void _R( T &x ) { cin>>x; }

void _R( int &x ) { scanf("%d",&x); }

void _R( int64_t &x ) { scanf("%" PRId64,&x); }

void _R( double &x ) { scanf("%lf",&x); }

void _R( char &x ) { scanf(" %c",&x); }

void _R( char *x ) { scanf("%s",x); }

void R() {}

template<class T, class... U> void R( T& head, U&... tail ) { _R(head); R(tail...); }



template<class T> void _W( const T &x ) { cout<<x; }

void _W( const int &x ) { printf("%d",x); }

void _W( const int64_t &x ) { printf("%" PRId64,x); }

void _W( const double &x ) { printf("%.16f\n",x); }

void _W( const char &x ) { putchar(x); }

void _W( const char *x ) { printf("%s",x); }

template<class T> void _W( const vector<T> &x ) { for (auto i = x.begin(); i != x.end(); _W(*i++)) if (i != x.cbegin()) putchar(' '); }

void W() {}

template<class T, class... U> void W( const T& head, const U&... tail ) { _W(head); putchar(sizeof...(tail)?' ':'\n'); W(tail...); }



template<class T> inline bool chmax( T &a, const T &b ) { return b>a ? a=b,true : false; }

template<class T> inline bool chmin( T &a, const T &b ) { return b<a ? a=b,true : false; }

template<class T, class F=less<T>> void sort_uniq( vector<T> &v, F f=F() ) {

    sort(begin(v),end(v),f);

    v.resize(unique(begin(v),end(v))-begin(v));

}



template<class T> using MaxHeap = priority_queue<T>;

template<class T> using MinHeap = priority_queue<T, vector<T>, greater<T>>;



#ifdef UNO

template<class T> void _dump(const char *s, T &&head) { cerr << s << "=" << head << endl; }

template<class T, class... Args> void _dump(const char *s, T &&head, Args &&... tail) {

    for (int c = 0; *s != ',' || c != 0; cerr << *s++) {

        if (*s == '(' || *s == '[' || *s == '{') c++;

        if (*s == ')' || *s == ']' || *s == '}') c--;

    }

    cerr << "=" << head << ", ";

    _dump(s + 1, tail...);

}

#define dump(...) do { fprintf(stderr, "%s:%d - ", __PRETTY_FUNCTION__, __LINE__); _dump(#__VA_ARGS__, __VA_ARGS__); } while (0)



template<class Iter> ostream &_out(ostream &s, Iter b, Iter e) {

    s << "[";

    for (auto it = b; it != e; it++) s << (it == b ? "" : " ") << *it;

    return s << "]";

}



template<class A, class B> ostream &operator<<(ostream &s, const pair<A, B> &p) { return s << "(" << p.first << "," << p.second << ")"; }

template<class T> ostream &operator<<(ostream &s, const vector<T> &c) { return _out(s, ALL(c)); }

template<class T, size_t N> ostream &operator<<(ostream &s, const array<T, N> &c) { return _out(s, ALL(c)); }

template<class T> ostream &operator<<(ostream &s, const set<T> &c) { return _out(s, ALL(c)); }

template<class A, class B> ostream &operator<<(ostream &s, const map<A, B> &c) { return _out(s, ALL(c)); }

#else

#define dump(...)

#endif

// }}}



const int MAX_N=11,MAX_M=10001;

int n,m;

int a[MAX_N][MAX_M];



void flip( int i ) {

    REP(j,m) a[i][j]^=1;

}



void solve() {

    int ans=0;

    REP(mask,1<<n) {

        REP(i,n) if ( mask>>i&1 ) flip(i);

        int res=0;

        REP(j,m) {

            int cnt=0;

            REP(i,n) if ( a[i][j] ) cnt++;

            res+=max(cnt,n-cnt);

        }

        chmax(ans,res);

        REP(i,n) if ( mask>>i&1 ) flip(i);

    }

    W(ans);

}

int main() {

    while ( 1 ) {

        R(n,m);

        if ( n==0&&m==0 ) break;

        REP(i,n) REP(j,m) R(a[i][j]);

        solve();

    }

    return 0;

}