土下座しながら探索中

主に競技プログラミング

AOJ 2142 : Bitwise Kingdom

問題リンク:Bitwise Kingdom | Aizu Online Judge


解法:
最初に求るビット列に何個1が含まれているのかを考える
Nビット中i個1を立てた時の組み合わせの数をどんどん足していき、和がM以上になった時点でループを打ち切る
(iは1の数で1から最大Nまで)

これで何個1を立てるかが分かったので、あとはそれをどこに配置するかを決める
ループで左から順に、その場所に0を置いたとするとその他の場所の1と0の組み合わせの数が求まるので
その数を加えたときに和がMを超えるか超えないかで0を置くか1を置くかを判断する

コード:

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define inf (1LL<<63)
#define MAX 70
#define deb(a) cout << #a << " " << a << endl

using namespace std;

typedef long long ll;

ll N,M;
ll C[MAX][MAX];

void makeC()
{
  C[0][0] = 1;
  rep(i,MAX-1)rep(j,i+1)
    {
      C[i+1][j] += C[i][j];
      if(j+1<MAX)C[i+1][j+1] += C[i][j];
    }
}

void compute()
{
  M--;
  if(M == 0)
    {
      cout << string(N,'0') << endl;
      return;
    }
  string ans = "";
  int NumberOfBits = 1;
  ll sum = 0;
  while(true)
    {
      sum += C[N][NumberOfBits]; 
      if(sum >= M)break;
      NumberOfBits++;
    }
  sum -= C[N][NumberOfBits];
  sum = M - sum;

  for(int i=N;i>=1;i--)
    {
      ll cost = sum - C[i-1][NumberOfBits];
      if(cost >  0)
	{
	  ans += "1";
	  sum -= C[i-1][NumberOfBits];
	  NumberOfBits--;
	}
      else ans += "0";
    }

  cout << ans << endl;
}

int main()
{
  makeC();

   while(cin >> N >> M,N|M)compute();

  return 0;
}