#include <iostream>
#include <vector>

using namespace std;

void RasporediVodu(vector<vector<long long>>* MatricaTokova, long long KolicinaVode,int Red, int LevaPozicija, int DesnaPozicija) 
{
	long long levaKolicina = 0, desnaKolicina = 0;
	if (DesnaPozicija >= (*MatricaTokova)[0].size()) //Sva voda treba da ide na levo
	{
		(*MatricaTokova).at(Red).at(LevaPozicija) += KolicinaVode;
	}
	else if (LevaPozicija < 0) //Sva voda treba da ide na desno
	{
		(*MatricaTokova).at(Red).at(DesnaPozicija) += KolicinaVode;
	}
	else //Treba rasporediti vodu na obe strane
	{
		if (KolicinaVode % 2 == 1) //Postoji visak i treba da se rasporedi
		{
			if (Red % 2 == 0)
			{
				desnaKolicina++;
			}
			else
			{
				levaKolicina++;
			}
			KolicinaVode--;
		}
		levaKolicina += KolicinaVode / 2;
		desnaKolicina += KolicinaVode / 2;
		(*MatricaTokova).at(Red).at(LevaPozicija) += levaKolicina;
		(*MatricaTokova).at(Red).at(DesnaPozicija) += desnaKolicina;

	}
}
//Levi kraj je prvo polje koje JE stena
//Vraca duzinu bloka
int RasporediVoduNadBlokom(vector<vector<long long>>* MatricaTokova, vector<vector<bool>> Vodopad, int RedUKomBlok, int LeviKrajBloka)
{
	long long kolicinaVode = (*MatricaTokova).at(RedUKomBlok - 1).at(LeviKrajBloka);
	int i = LeviKrajBloka+1;
	while (i != Vodopad[RedUKomBlok].size() && Vodopad[RedUKomBlok][i] == 0)
	{
		kolicinaVode += (*MatricaTokova).at(RedUKomBlok-1).at(i);
		i++;
	}
	RasporediVodu(MatricaTokova, kolicinaVode, RedUKomBlok, LeviKrajBloka - 1, i);
	return i - LeviKrajBloka;
}

void RasporediVoduNadJednimKamenom(vector<vector<long long>>* MatricaTokova, int RedKamena, int KolonaKamena)
{
	long long kolicinaVode = (*MatricaTokova).at(RedKamena-1).at(KolonaKamena);
	RasporediVodu(MatricaTokova, kolicinaVode, RedKamena, KolonaKamena - 1, KolonaKamena + 1);
}

vector<long long> SimulirajTok(vector<vector<bool>> vodopad) 
{
	vector<vector<long long>> tokovi = vector<vector<long long>>(vodopad.size());
	tokovi[0] = vector<long long>(vodopad[0].size(), 1);
	for (int i = 1; i < vodopad.size(); i++)
	{
		tokovi[i] = vector<long long>(vodopad[0].size());
		for (int j = 0; j < vodopad[0].size(); j++)
		{
			if (vodopad[i][j] == 0) 
			{
				int pomeriZbogBloka = 0;
				if ((j-1 > 0 && vodopad[i][j-1] == 0) ||
					(j+1 < vodopad[0].size() && vodopad[i][j+1] == 0)) //Neki od suseda je takodje stena
				{
					pomeriZbogBloka = RasporediVoduNadBlokom(&tokovi, vodopad, i, j);
				}
				else //Ni jedan od suseda nije stena
				{
					RasporediVoduNadJednimKamenom(&tokovi, i, j);
				}
				tokovi[i][j] = 0; //Stena ima protok nula
				j += pomeriZbogBloka;
				if (pomeriZbogBloka > 0)
				{
					if (vodopad[i][j] == 1)
					{
						tokovi[i][j] += tokovi[i - 1][j];
					}
				}
			}
			else
			{
				tokovi[i][j] += tokovi[i-1][j]; //Samo slije vodu odozgo ako je prazno polje
			}
		}
	}
	return tokovi[vodopad.size()-1];
}
int main()
{
	int h, n;
	cin >> h >> n;
	vector<vector<bool>> vodopad = vector<vector<bool>>(h+1);
	vodopad[0] = vector<bool>(n, true);
	for (int i = 1; i < h+1; i++)
	{
		vodopad[i] = vector<bool>(n);
		for (int j = 0; j < n; j++)
		{
			int unos;
			cin >> unos;
			vodopad[i][j] = bool(unos);
		}
	}
	auto poslednjiRed = SimulirajTok(vodopad);
	for (int i = 0; i < poslednjiRed.size(); i++)
	{
		cout << poslednjiRed[i] << " ";
	}
	return 0;
}