Problem:
Score : 400 points

Problem Statement

Let \mathrm{popcount}(n) be the number of 1s in the binary representation of n.
For example, \mathrm{popcount}(3) = 2, \mathrm{popcount}(7) = 3, and \mathrm{popcount}(0) = 0.

Let f(n) be the number of times the following operation will be done when we repeat it until n becomes 0: "replace n with the remainder when n is divided by \mathrm{popcount}(n)." (It can be proved that, under the constraints of this problem, n always becomes 0 after a finite number of operations.)

For example, when n=7, it becomes 0 after two operations, as follows:

\mathrm{popcount}(7)=3, so we divide 7 by 3 and replace it with the remainder, 1.

\mathrm{popcount}(1)=1, so we divide 1 by 1 and replace it with the remainder, 0.

You are given an integer X with N digits in binary.
For each integer i such that 1 \leq i \leq N, let X_i be what X becomes when the i-th bit from the top is inverted.
Find f(X_1), f(X_2), \ldots, f(X_N).

Constraints

1 \leq N \leq 2 \times 10^5

X is an integer with N digits in binary, possibly with leading zeros.

Input

Input is given from Standard Input in the following format:

N
X

Output

Print N lines. The i-th line should contain the value f(X_i).

Sample Input 1

3
011

Sample Output 1

2
1
1

X_1 = 7, which will change as follows: 7 \rightarrow 1 \rightarrow 0. Thus, f(7) = 2.

X_2 = 1, which will change as follows: 1 \rightarrow 0. Thus, f(1) = 1.

X_3 = 2, which will change as follows: 2 \rightarrow 0. Thus, f(2) = 1.

Sample Input 2

23
00110111001011011001110

Sample Output 2

2
1
2
2
1
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
1
3

Solution in C# (.NET Core 3.1.201) (judge verdict: Accepted)

using Atcoder_Library_NetCore3;

using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;

using System.Text;

using static Atcoder_Library_NetCore3.MyBitUtil;
using static Atcoder_Library_NetCore3.MyInputUtil;
using static System.Console;

namespace Atcoder_Template_NetCore3
{
    class Program
    {
        static void Main()
        {
            const int max = 210_000;

            var test = int.MaxValue.ToBitArray();
            var testStr = string.Join("", test);

            int[] table = new int[max + 1];
            table[1] = 1;
            for (int i = 2; i < table.Length; i++)
            {
                var value = i % CountOne(i);
                if (value == 0)
                {
                    table[i] = 1;
                }
                else
                {
                    table[i] = table[value] + 1;
                }
            }

            var n = ReadInput<int>();
            string input = ReadLine();

            int[] modArr1 = new int[n];
            int[] modArr2 = new int[n];

            var oneCount = input.Count(c => c == '1');
            var mod1 = oneCount - 1;
            var mod2 = oneCount + 1;

            if (mod1 > 0)
            {
                for (int i = 0; i < n; i++)
                {
                    modArr1[i] = (int)GetMod((n - i - 1), mod1);
                }
            }

            for (int i = 0; i < n; i++)
            {
                modArr2[i] = (int)GetMod((n - i - 1), mod2);
            }

            var modSum1 = 0l;
            var modSum2 = 0l;
            if (mod1 > 0)
            {
                modSum1 = input.Select((c, i) =>
                {
                    if (c == '0')
                    {
                        return 0l;
                    }
                    else
                    {
                        return (long)modArr1[i];
                    }
                }).Sum() % mod1;
            }
            modSum2 = input.Select((c, i) =>
            {
                if (c == '0')
                {
                    return 0l;
                }
                else
                {
                    return (long)modArr2[i];
                }
            }).Sum() % mod2;


            StringBuilder stringBuilder = new StringBuilder();
            for (int i = 0; i < n; i++)
            {
                if (input[i] == '1')
                {
                    if (mod1 == 0)
                    {
                        stringBuilder.AppendLine("0");
                        continue;
                    }
                    var res = (modSum1 - modArr1[i]) % mod1;
                    if (res < 0) res = mod1 + res;
                    stringBuilder.AppendLine((table[res] + 1).ToString());
                }
                else
                {
                    var res = (modSum2 + modArr2[i]) % mod2;
                    //if (res < 0) res = mod2 + res;
                    stringBuilder.AppendLine((table[res] + 1).ToString());
                }
            }

            Console.WriteLine(stringBuilder.ToString());
        }

        static long GetMod(long x, long mod)
        {
            if (x == 0)
            {
                return 1 % mod;
            }
            else if ((x & 1) == 0)
            {
                var a = GetMod(x >> 1, mod);
                return a * a % mod;
            }
            else
            {
                return GetMod(x - 1, mod) * 2 % mod;
            }
        }

        static int CountOne(int x)
        {
            var sum = 0;
            const int mask = 1;
            while (x > 0)
            {
                sum += x & mask;
                x >>= 1;
            }
            return sum;
        }
    }

    // ABC157_D　の途中のやつ
    /*
   var(personCount, frindCount, blockCount) = ReadInput3<int>();

           UnionFindTree unionFindTree = new UnionFindTree(personCount);
           for(int i = 0; i<frindCount; i++)
           {
               var(a, b) = ReadInput2<int>();
               unionFindTree.Unite(a - 1, b - 1);
           }

           for(int i = 0; i<blockCount; i++)
           {

           }
    */
}

namespace Atcoder_Library_NetCore3
{
    /// <summary>
    /// グループへの所属判定とグループの結合を高速に行う機能を提供します。
    /// </summary>
    public class UnionFindTree
    {
        private readonly List<int> parentIndexs;
        private readonly List<int> ranks;

        /// <summary>
        /// 要素が空の状態として <see cref="UnionFindTree"/> の新しいインスタンスを初期化します。
        /// </summary>
        public UnionFindTree()
        {
            parentIndexs = new List<int>();
            ranks = new List<int>();
        }

        /// <summary>
        /// 指定の要素数で <see cref="UnionFindTree"/> の新しいインスタンスを初期化します。
        /// </summary>
        /// <param name="count">初期状態として存在する要素数。</param>
        public UnionFindTree(int count)
        {
            parentIndexs = new List<int>(Enumerable.Range(1, count));
            var arr = new int[count];
            Array.Fill(arr, 1);
            ranks = new List<int>(arr);
        }

        /// <summary>
        /// 2つの要素の間に結合を張ります。
        /// </summary>
        public void Unite(int a, int b)
        {
            if (IsSameGroup(a, b))
            {
                return;
            }
            else
            {
                var ra = ranks[a];
                var rb = ranks[b];

                if (ra == rb)
                {
                    var bParent = FindParent(b);
                    parentIndexs[bParent] = a;
                    ranks[a]++;
                }
                else if (ra > rb)
                {
                    var bParent = FindParent(b);
                    parentIndexs[bParent] = a;
                }
                else
                {
                    var aParent = FindParent(a);
                    parentIndexs[aParent] = b;
                }
            }
        }

        /// <summary>
        /// 2つの要素が結合で結ばれているかどうか調べます。間接的に結ばれている場合を含みます。
        /// </summary>
        public bool IsSameGroup(int a, int b)
        {
            return FindParent(a) == FindParent(b);
        }

        /// <summary>
        /// 新しい要素を親として追加します。
        /// </summary>
        public void Add()
        {
            parentIndexs.Add(1);
            ranks.Add(1);
        }

        private int FindParent(int index)
        {
            if (parentIndexs[index] == index)
            {
                return index;
            }
            else
            {
                var parent = FindParent(parentIndexs[index]);
                parentIndexs[index] = parent;
                return parent;
            }
        }
    }

    /// <summary>
    /// Bit取得、およびbit全探索を提供します。
    /// </summary>
    internal static class MyBitUtil
    {
        /// <summary>
        /// 指定の桁のビットを取得します。
        /// </summary>
        /// <param name="count">取得する桁。</param>
        /// <returns></returns>
        public static int GetBit(this int num, int count)
        {
            var x = num >> (count - 1);
            const int mask = 1;
            return x & mask;
        }

        /// <summary>
        /// 各ビットの値を <see cref="int"/> 配列として取得します。
        /// 下位の桁が配列の前に来ます。
        /// </summary>
        public static int[] ToBitArray(this int num)
        {
            const int size = sizeof(int) * 8;
            var array = new int[size];
            for (var i = 0; i < size; i++)
            {
                array[i] = num.GetBit(i + 1);
            }
            return array;
        }

        public static int BitToInt32(int[] bitArray)
        {
            var result = 0;
            for (int i = 0; i < bitArray.Length; i++)
            {
                result += bitArray[i] << i;
            }
            return result;
        }

        /// <summary>
        /// 各ビットを真偽値として解釈した結果を <see cref="bool"/> 配列として取得します。
        /// 下位の桁が配列の前に来ます。
        /// </summary>
        public static bool[] ToBoolArray(this int num)
        {
            const int size = sizeof(int) * 8;
            var array = new bool[size];
            for (var i = 0; i < size; i++)
            {
                array[i] = num.GetBit(i + 1) == 1;
            }
            return array;
        }

        /// <summary>
        /// Bit全探索を行います。
        /// </summary>
        /// <param name="count">対象とする要素の個数。30以下である必要があります。</param>
        /// <param name="action">各パターンに対して行う処理</param>
        public static void BitAllSearch(int count, Action<bool[]> action)
        {
            var max = 1 << count;
            for (var i = 0; i < max; i++)
            {
                action.Invoke(i.ToBoolArray());
            }
        }

        /// <summary>
        /// 指定したコレクションに対してBit全探索を行います。
        /// </summary>
        /// <param name="list">対象とする集合。要素数30以下である必要があります。</param>
        /// <param name="action">各パターンに対して行う処理</param>
        public static IEnumerable<IEnumerable<T>> GetAllPatterns<T>(this IReadOnlyList<T> list)
        {
            var max = 1 << list.Count;
            for (var i = 0; i < max; i++)
            {
                var usePattern = i.ToBoolArray();
                IEnumerable<T> query = list.Where((item, j) => usePattern[j]);
                yield return query;
            }
        }
    }

    /// <summary>
    /// 標準入力の高機能な読み取りを提供します。
    /// </summary>
    internal static class MyInputUtil
    {
        private const char separator = ' ';

        /// <summary>
        /// 標準入力から入力を1つ指定の型に変換して読み取ります。
        /// </summary>
        /// <typeparam name="T">変換先として指定する型。</typeparam>
        /// <param name="converter">変換に使用する関数。<c>null</c>の場合は自動決定を試みます。</param>
        /// <returns></returns>
        public static T ReadInput<T>(Func<string, T> converter = null)
        {
            if (converter is null)
            {
                converter = GetConverter<T>();
            }
            return converter.Invoke(Console.ReadLine());
        }

        #region 一定個数の入力の読み取り
        // 用法は ReadInput<T> と共通です。
        [GeneratedCode(null, "2.1")]
        public static ValueTuple<T, T> ReadInput2<T>(Func<string, T> converter = null)
        {
            if (converter is null) { converter = GetConverter<T>(); }
            var input = Console.ReadLine().Split(separator);
            return (converter.Invoke(input[0]), converter.Invoke(input[1]));
        }
        [GeneratedCode(null, "2.1")]
        public static ValueTuple<T, T, T> ReadInput3<T>(Func<string, T> converter = null)
        {
            if (converter is null) { converter = GetConverter<T>(); }
            var input = Console.ReadLine().Split(separator);
            return (converter.Invoke(input[0]), converter.Invoke(input[1]), converter.Invoke(input[2]));
        }
        [GeneratedCode(null, "2.1")]
        public static ValueTuple<T, T, T, T> ReadInput4<T>(Func<string, T> converter = null)
        {
            if (converter is null) { converter = GetConverter<T>(); }
            var input = Console.ReadLine().Split(separator);
            return (converter.Invoke(input[0]), converter.Invoke(input[1]), converter.Invoke(input[2]), converter.Invoke(input[3]));
        }
        [GeneratedCode(null, "2.1")]
        public static ValueTuple<T, T, T, T, T> ReadInput5<T>(Func<string, T> converter = null)
        {
            if (converter is null) { converter = GetConverter<T>(); }
            var input = Console.ReadLine().Split(separator);
            return (converter.Invoke(input[0]), converter.Invoke(input[1]), converter.Invoke(input[2]), converter.Invoke(input[3]), converter.Invoke(input[4]));
        }
        [GeneratedCode(null, "2.1")]
        public static ValueTuple<T, T, T, T, T, T> ReadInput6<T>(Func<string, T> converter = null)
        {
            if (converter is null) { converter = GetConverter<T>(); }
            var input = Console.ReadLine().Split(separator);
            return (converter.Invoke(input[0]), converter.Invoke(input[1]), converter.Invoke(input[2]), converter.Invoke(input[3]), converter.Invoke(input[4]), converter.Invoke(input[5]));
        }
        [GeneratedCode(null, "2.1")]
        public static ValueTuple<T, T, T, T, T, T, T> ReadInput7<T>(Func<string, T> converter = null)
        {
            if (converter is null) { converter = GetConverter<T>(); }
            var input = Console.ReadLine().Split(separator);
            return (converter.Invoke(input[0]), converter.Invoke(input[1]), converter.Invoke(input[2]), converter.Invoke(input[3]), converter.Invoke(input[4]), converter.Invoke(input[5]), converter.Invoke(input[6]));
        }
        #endregion

        /// <summary>
        /// 標準入力から配列を読み取ります。
        /// </summary>
        /// <returns></returns>
        public static T[] ReadArray<T>(Func<string, T> converter = null)
        {
            var str = ReadLine().Split(separator);
            if (converter is null)
            {
                converter = GetConverter<T>();
            }
            return str.Select(s => converter.Invoke(s)).ToArray();
        }

        #region 変換用メソッド
        /// <summary>
        /// 文字列を指定の型に変換します。
        /// </summary>
        /// <typeparam name="T">変換先の型。すべての組み込み型がサポートされます。</typeparam>
        /// <param name="str">変換元の文字列</param>
        /// <exception cref="NotSupportedException">指定の型引数がサポートされない場合にスローされる例外。</exception>
        /// <remarks>大量の値を処理する場合、このメソッドは低速です。<see cref="ConvertTo{T}(string[])"/> の使用を検討してください。</remarks>
        public static T ConvertTo<T>(string str)
        {
            return GetConverter<T>().Invoke(str);
        }

        /// <summary>
        /// 文字列配列を指定の型の配列に変換します。
        /// </summary>
        /// <typeparam name="T">変換先の型。すべての組み込み型がサポートされます。</typeparam>
        /// <param name="str">変換元の文字列配列</param>
        /// <exception cref="NotSupportedException">指定の型引数がサポートされない場合にスローされる例外。</exception>
        public static T[] ConvertTo<T>(string[] str)
        {
            var conveter = GetConverter<T>();
            var array = new T[str.Length];
            for (var i = 0; i < str.Length; i++)
            {
                array[i] = conveter.Invoke(str[i]);
            }
            return array;
        }

        private static Func<string, T> GetConverter<T>() => GetConverterOrDefault<T>() ?? throw new NotSupportedException("この型に対する変換関数の取得はサポートされていません");
        private static bool TryGetConverter<T>(out Func<string, T> func)
        {
            func = GetConverterOrDefault<T>();
            return !(func is null);
        }

        private static Func<string, T> GetConverterOrDefault<T>()
        {
            Type type = typeof(T);
            Func<string, T> conveter;

            // 出現頻度が高そうなものを上
            if (type == typeof(int))
            {
                conveter = str => (T)(object)int.Parse(str);
            }
            else if (type == typeof(long))
            {
                conveter = str => (T)(object)long.Parse(str);
            }
            else if (type == typeof(double))
            {
                conveter = str => (T)(object)double.Parse(str);
            }
            else if (type == typeof(decimal))
            {
                conveter = str => (T)(object)decimal.Parse(str);
            }
            else if (type == typeof(float))
            {
                conveter = str => (T)(object)float.Parse(str);
            }
            else if (type == typeof(char))
            {
                conveter = str => (T)(object)str[0];
            }
            else if (type == typeof(short))
            {
                conveter = str => (T)(object)short.Parse(str);
            }
            else if (type == typeof(byte))
            {
                conveter = str => (T)(object)byte.Parse(str);
            }
            else if (type == typeof(bool))
            {
                conveter = str => (T)(object)bool.Parse(str);
            }
            else if (type == typeof(ulong))
            {
                conveter = str => (T)(object)ulong.Parse(str);
            }
            else if (type == typeof(uint))
            {
                conveter = str => (T)(object)uint.Parse(str);
            }
            else if (type == typeof(ushort))
            {
                conveter = str => (T)(object)ushort.Parse(str);
            }
            else if (type == typeof(sbyte))
            {
                conveter = str => (T)(object)sbyte.Parse(str);
            }
            else if (type == typeof(string))
            {
                conveter = str => (T)(object)str;
            }
            else if (type == typeof(object))
            {
                conveter = str => (T)(object)str;
            }
            else
            {
                conveter = null;
            }

            return conveter;
        }
        #endregion
    }
}