Sunday, January 3, 2016

UVa 11472 - Beautiful Numbers

Accepted date: 2016-01-03
Run Time: 0.006
Ranking (as of 2016-01-03): 11 out of 453
Language: C++

/*
  UVa 11472 - Beautiful Numbers

  To build using Visual Studio 2012:
    cl -EHsc -O2 UVa_11472_Beautiful_Numbers.cpp
*/

#include <cstdio>

const int N_max = 10, M_max = 100, mask_max = 1 << N_max, divisor = 1000000007;
int nrs[M_max + 1][N_max][mask_max];
  // [number of digits][lastdigit used][mask of used digits]

int main()
{
  for (int n = 1; n < N_max; n++)
    nrs[1][n][1 << n] = 1;
  for (int m = 2; m <= M_max; m++) {
    for (int i = 1; i < mask_max; i++)
      nrs[m][1][i | 1] = nrs[m - 1][0][i];
    for (int n = 1; n < N_max - 1; n++)
      for (int i = 1; i < mask_max; i++) {
        nrs[m][n - 1][i | 1 << (n - 1)] += nrs[m - 1][n][i];
        nrs[m][n - 1][i | 1 << (n - 1)] %= divisor;
        nrs[m][n + 1][i | 1 << (n + 1)] += nrs[m - 1][n][i];
        nrs[m][n + 1][i | 1 << (n + 1)] %= divisor;
      }
    for (int i = 1; i < mask_max; i++) {
      nrs[m][N_max - 2][i | 1 << (N_max - 2)] += nrs[m - 1][N_max - 1][i];
      nrs[m][N_max - 2][i | 1 << (N_max - 2)] %= divisor;
    }
  }

  int T;
  scanf("%d", &T);
  while (T--) {
    int N, M;
    scanf("%d %d", &N, &M);
    int mask = 1 << N, nr = 0;
    for (int m = 2; m <= M; m++)
      for (int n = 0; n < N; n++) {
        nr += nrs[m][n][mask - 1];
        nr %= divisor;
      }
    printf("%d\n", nr);
  }
  return 0;
}

4 comments:

  1. Can You Share The Idea to solve this Problem ?

    ReplyDelete
  2. I got a hint from
    https://uva.onlinejudge.org/board/viewtopic.php?f=42&t=71043
    that says:
    I also used an O(2^N * N * M) solution.
    My state is dp[length][used digits][first digit],
    where dp[i][j][k] = number of ways to form a number with i digits,
    such that the first digit is k and j is a bitwise mask indicating which digits I have used.
    This method took 1 second (slow!) using memoization.

    And, to get an idea of recurrence relation,
    wrote down [number of digits][lastdigit used][mask of used digits] for N = 3, M = 1 - 5, like below.
    Here, the lines starting with '+' are valid beautiful numbers, while the lines starting with '-' are not.

    M:1
    0
    [1][0][001]:0
    1
    [1][1][010]
    2
    [1][2][100]

    M:2
    01 = 0 + 1
    [2][1][011] = [1][0][001]
    10 = 1 + 0
    [2][0][011] = [1][1][010]
    12 = 1 + 2
    [2][2][110] = [1][1][010]
    21 = 2 + 1
    [2][1][110] = [1][2][100]

    M:3
    010 = 01 + 0
    [3][0][011] = [2][1][011]
    - 012 = 01 + 2
    [3][2][111] = [2][1][011]
    101 = 10 + 1
    [3][1][011] = [2][0][011]
    121 = 12 + 1
    [3][1][110] = [2][2][110]
    + 210 = 21 + 0
    [3][0][111] = [2][1][110]
    212 = 21 + 2
    [3][2][110] = [2][1][110]

    M:4
    0101 = 010 + 1
    [4][1][011] = [3][0][011]
    - 0121 = 012 + 1
    [4][1][111] = [3][2][111]
    1010 = 101 + 0
    [4][0][011] = [3][1][011]
    + 1012 = 101 + 2
    [4][2][111] = [3][1][011]
    + 1210 = 121 + 0
    [4][0][111] = [3][1][110]
    1212 = 121 + 2
    [4][2][110] = [3][1][110]
    + 2101 = 210 + 1
    [4][1][111] = [3][0][111]
    2121 = 212 + 1
    [4][1][110] = [3][2][110]

    M:5
    01010 = 0101 + 0
    [5][0][011] = [4][1][011]
    - 01012 = 0101 + 2
    [5][2][111] = [4][1][011]
    - 01210 = 0121 + 0
    [5][0][111] = [4][1][111]
    - 01212 = 0121 + 2
    [5][2][111] = [4][1][111]
    10101 = 1010 + 1
    [5][1][011] = [4][0][011]
    + 10121 = 1012 + 1
    [5][1][111] = [4][2][111]
    + 12101 = 1210 + 1
    [5][1][111] = [4][0][111]
    12121 = 1212 + 1
    [5][1][110] = [4][2][110]
    + 21010 = 2101 + 0
    [5][0][111] = [4][1][111]
    + 21012 = 2101 + 2
    [5][2][111] = [4][1][111]
    + 21210 = 2121 + 0
    [5][0][111] = [4][1][110]
    21212 = 2121 + 2
    [5][2][110] = [4][1][110]

    And then, I wrote a solution.

    ReplyDelete
    Replies
    1. Thaks for such a Fast Reply . I am trying to have this idea . I got several ideas to solve a problem from your Blog. They are great. I would like to request you to Share the Idea / Hint for a problem instead Code . You Can Share Code As an Extension. But an Idea Can help a Solver Much more to think .

      Delete
  3. OK, from now on, I will try to add some comments/explanatations to my solutions.

    ReplyDelete