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 rm = 0L;
	if( 0 < pm )
	{
		foreach( i, b; x )
		{
			if( b == '1' ) rm = ( rm + remainder!2( 1, n - 1 - i, pm ) ) % pm;
		}
	}
	
	// x % ( x._popcnt + 1 ) を計算
	auto pp = px + 1;
	auto rp = 0L;
	foreach( i, b; x )
	{
		if( b == '1' ) rp = ( rp + remainder!2( 1, n - 1 - i, pp ) ) % 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 = ( rm - remainder!2( 1, n - 1 - i, pm ) + pm ) % pm;
		}
		else
		{
			r = ( rp + remainder!2( 1, n - 1 - i, pp ) ) % pp;
		}
		ans++;
		
		// 二回目以降の計算
		for( ; 0 < r; r %= r._popcnt )
		{
			ans++;
		}
	}
	return anss.to!( string[] ).join( "\n" );
}

// ( a * B ^^ n ) % m を計算
auto remainder( long B )( long a, long n, long m )
{
	static long[][] memo;
	if( m <= 0 ) return 0L;
	if( memo.length <= m ) memo.length = m + 1;
	if( memo[ m ].length <= n )
	{
		if( memo[ m ].empty ) memo[ m ] = [ 1L % m ];
		auto i = memo[ m ].length.signed - 1;
		memo[ m ].length = n + 1;
		for( ; i < n; i++ )
		{
			memo[ m ][ i + 1 ] = ( memo[ m ][ i ] * B ) % m;
		}
	}
	return ( a * memo[ m ][ n ] ) % m;
}
