Problem:
アカベコ２０

　

「アカベコ２０」は、イヅア地方の専用劇場で公演を開催しているグループです。アカベコ２０のそれぞれのメンバーは、ある一定の日数ごとに公演に参加することになっています。

今日の公演ではメンバーが全員参加していました。プロデューサーであるあなたは、メンバーから、今後の公演のメンバーの組み合わせを教えてほしい、と頼まれました。あなたは、公演に参加するメンバーの組み合わせがいくつあるのかを数えることにしました。

アカベコ２０のメンバー数と、それぞれのメンバーが公演に参加する周期が１日単位で与えられたとき、参加するメンバーの組み合わせが何通りあるかを数えるプログラムを作成せよ。このとき、グループは同じメンバーで永遠に存続すると仮定する。ただし、だれも参加しない場合は組み合わせに含めないこととする。

入力

入力は以下の形式で与えられる。

$N$
$p_1$ $p_2$ ... $p_N$

１行目にアカベコ２０のメンバー数$N$ ($1 \leq N \leq 20$)が与えられる。続く１行に、それぞれのメンバーが公演に参加する周期$p_i$ ($1 \leq p_i \leq 40$)が与えられる。

出力

参加するメンバーの組み合わせの数を１行に出力する。

入出力例

入力例１

3
3 5 2

出力例１

7

入力例２

3
2 3 6

出力例２

3

周期が２日のメンバーのみが参加する公演，周期が３日のメンバーのみが参加する公演，周期が２日、３日、６日のメンバーが参加する公演の３通りとなる。

Solution in C (judge verdict: Accepted)

#include<stdio.h>
typedef unsigned long long ull;
int N, A[20], cnt;
int S[20]; // select?

ull gcd(ull x, ull y){
  ull r, t;
  if ( x < y ) { t = x; x = y; y = t; }
  while( y > 0 ){
    r = x % y;
    x = y;
    y = r;
  }
  return x;
}
ull lcm(ull x, ull y){
  return x/gcd(x, y)*y;
}

void rec(int p, ull LCM, int sum){
  int ok;
  if ( p == N ){
    ok = (sum > 0); // 一人以上いる
    for ( int i = 0; i < N; i++ ){
      if ( LCM >= A[i] && LCM % A[i] == 0 ){
        if ( S[i] == 0 ) ok = 0; //　選ばれていない人の周期
      }
    }
    if ( ok ) cnt++;
    return;
  }
  S[p] = 1;
  rec(p+1, lcm(LCM, A[p]), sum+1);
  S[p] = 0;
  rec(p+1, LCM, sum);
}
int main(){
  int i;
  scanf("%d", &N);
  for ( i = 0; i < N; i++ ) scanf("%d", &A[i]);
  cnt = 0;
  rec(0, 1, 0);
  printf("%d\n", cnt);
  return 0;
}