Official

F - Enumerate Sequences Editorial by en_translator


There are \(5^8=390625\) sequences of length \(8\) consisting of integers between \(1\) and \(5\). Since the number of sequences to print is always not more than this count, we do not have to worry about to much output.

Approach 1. Use recursion to enumerate

  • Fix the first element in ascending order.
  • Once the first element is fixed, call the recursion to fix the second element in ascending order.
  • \(\dots\)
  • Once all the elements are ready, check if the total sum is a multiple of \(K\) and print it.

Implementing this recursion will be accepted.

Sample code (C++):

#include<bits/stdc++.h>

using namespace std;

int n,k;
int r[8];
int seq[8];

void solve(int lv){
  if(lv==n){
    int s=0;
    for(int i=0;i<n;i++){ s+=seq[i]; }
    if(s%k==0){
      for(int i=0;i<n;i++){
        if(i){cout << " ";}
        cout << seq[i];
      }cout << "\n";
    }
    return;
  }
  for(int i=1;i<=r[lv];i++){
    seq[lv]=i;
    solve(lv+1);
  }
}

int main(){
  cin >> n >> k;
  for(int i=0;i<n;i++){
    cin >> r[i];
  }
  solve(0);
  return 0;
}

Approach 2. Decode integers corresponding to sequences

Ignoring the condition “multiple of \(K\),” there are \(P=R_1 \times R_2 \times \dots \times R_N\) possible sequences.
Actually, if you decode an integer between \(0\) and \(P-1\) as follows, the results are sorted in ascending order.

  • Let \(S\) be the decode result. Also, prepare a variable \(x \leftarrow t\).
  • For \(i = N\) down to \(1\), do the following.
    • Let \(S_i \leftarrow (x \% R_i)+1\). (\(p \% q\): the remainder when \(p\) is divided by \(q\))
    • Then, replace \(x\) with \(\displaystyle \frac{x}{R_i}\) (rounded down).

Intuitively, a sequence corresponds to a special \(N\)-ary representation.
For example, \(R=(6,3,2,5)\) can be regarded as \(1\)s place, \(5\)s place, \((5 \times 2)\)s place, and \((5 \times 2 \times 3)\)s place, from the last element (the least significant digit) in order. Here, \(A=(1,3,1,2)\) corresponds to \(0 \times 30 + 2 \times 10 + 0 \times 5 + 1\) (where each element between \(1\) and \(R_i\) is shifted to range in \(0\) through \(R_i-1\).)

Alternatively, one can use another decoding but finally sorting the obtained sequences. (For example in C++, sorting vector<vector<int>> rearranges the elements vector<int> in lexicographically order.)

Sample code (C++):

#include<bits/stdc++.h>

using namespace std;

int n,k;
int r[8];
int seq[8];

int main(){
  cin >> n >> k;
  int tot=1;
  for(int i=0;i<n;i++){
    cin >> r[i];
    tot*=r[i];
  }
  for(int t=0;t<tot;t++){
    int x=t;
    int s=0;
    for(int i=n-1;i>=0;i--){
      seq[i]=(x%r[i])+1;
      s+=seq[i];
      x/=r[i];
    }
    if(s%k==0){
      for(int i=0;i<n;i++){
        if(i){cout << " ";}
        cout << seq[i];
      }cout << "\n";
    }
  }
  return 0;
}

posted:
last update: