unittest
{
	assert( [ "3", "011" ].solve == "2\n1\n1" );
	assert( [ "23", "00110111001011011001110" ].solve == "2\n1\n2\n2\n1\n2\n2\n2\n2\n2\n2\n2\n2\n2\n2\n2\n2\n2\n2\n2\n2\n1\n3" );
	
	assert( [ "3", "000" ].solve == "1\n1\n1" );		// 追加ケース
	assert( [ "3", "100" ].solve == "0\n1\n2" );		// 追加ケース
	assert( [ "3", "111" ].solve == "2\n2\n1" );		// 追加ケース
}



import core.bitop;
import std.algorithm;
import std.conv;
import std.range;
import std.stdio;

void main()
{
	stdin.byLineCopy.solve.writeln;
}

auto solve( Range )( Range input )
if( isInputRange!Range && is( ElementType!Range == string ) )
{
	auto n = input.front.to!( long );
	input.popFront;
	auto x = input.front.to!( dchar[] );
	
	// 立っているビットをカウント
	auto px = x.count( '1' );
	
	// x % ( x._popcnt - 1 ) を計算
	auto pm = px - 1;
	auto rms = new long[ n ];
	auto rmt = 0L;
	if( 0 < pm )
	{
		for( auto i = 0L, r = 1L % pm; i < rms.length; i++, r = ( r << 1 ) % pm )
		{
			rms[ i ] = r;
			if( x[ n - 1 - i ] == '1' ) rmt = ( rmt + r ) % pm;
		}
	}
	
	// x % ( x._popcnt + 1 ) を計算
	auto pp = px + 1;
	auto rps = new long[ n ];
	auto rpt = 0L;
	for( auto i = 0L, r = 1L % pp; i < rps.length; i++, r = ( r << 1 ) % pp )
	{
		rps[ i ] = r;
		if( x[ n - 1 - i ] == '1' ) rpt = ( rpt + r ) % pp;
	}
	
	// f(xi)を計算
	auto anss = new long[ n ];
	foreach( i, ref ans, b; lockstep( anss, x ) )
	{
		// 一回目の計算（xが64bitに収まらないので事前計算＋ビット反転箇所の差分で計算）
		auto r = 0L;
		if( b == '1' )
		{
			if( pm == 0 ) continue;
			r = ( rmt - rms[ $ - 1 - i ] + pm ) % pm;
		}
		else
		{
			r = ( rpt + rps[ $ - 1 - i ] ) % pp;
		}
		ans++;
		
		// 二回目以降の計算
		for( auto p = r._popcnt; 0 < r; p = r._popcnt, r %= p )
		{
			ans++;
		}
	}
	return anss.to!( string[] ).join( "\n" );
}
