using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
public class Program {
    public static void Main() {
        string line;
        while ((line = System.Console.ReadLine ()) != null) { // 注意 while 处理多个 case
            int n = int.Parse(line);
            line = Console.ReadLine();
            string[] t = line.Split(' ');
            ulong[] ball = new ulong[t.Length];
            for(int i = 0; i < t.Length; i++) ball[i] = ulong.Parse(t[i]);
            //排序ball
            for(int i = 0; i < ball.Length; i++){
                bool swap = false;
                for(int j = 0; j < ball.Length - 1 - i; j++){
                    if(ball[j] > ball[j+1]){
                        ulong temp = ball[j];
                        ball[j] = ball[j+1];
                        ball[j+1] = temp;
                        swap = true;
                    }
                }
                if(!swap) break;
            }
            //递归遍历所有情况
            Console.WriteLine(recursion(0,ball,0,1));
        }    
    }
    //递归加球,每次加球只列举从index开始,每种各加1个的情况,不会出现一次递归加了两个一样的球
    public static int recursion(int index, ulong[] ball, ulong sum, ulong pro){
        int count = 0;
        while(index < ball.Length){
            sum += ball[index];
            pro *= ball[index];
            if(sum > pro) 
                count += 1 + recursion(index + 1, ball, sum, pro);
            else if(ball[index] == 1)
                count += recursion(index + 1, ball, sum, pro);
            else
                return count;
            ulong temp = ball[index];
            sum -= temp;
            pro /= temp;
            //定位到下一种球的位置
            while(++index < ball.Length){
                if(ball[index] != temp) 
                    break;
            }
        }
        return count;
    }
}

我们不从口袋里拿出球,而是把球一个一个放进口袋,并判断是否是幸运袋子。

为了遍历所有情况而不出现重复,我们举个例子:

对于1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,3,3,3,3,7,7,7

第一个球可以拿

1;2;3;7

第二次拿可以变成

1,1; 1,2; 1,3; 1,7;

2,2; 2,3; 2,7;

3,3; 3,7;

7,7;

我们发现显然第一次拿2的情况下,第二次不可以再拿1,因为2,1和 1,2是一样的

所以我们第i次拿的时候,只需要考虑从i-1次拿的球开始拿

代码思路:

先对ball数组从小到大排序,定义一个递归,它从index处开始拿球,列举第i次可以拿的球的情况,若某种情况下,是幸运袋子,那么count++,调用自身,拿第i+1次;若不满足,有两种情况:1.是在拿第一个球,且第一个球是1,那么我们拿这个球,然后调用自身拿下一个;2.不是第一个球,那么没有再往大的球拿的必要了,因为拿x不是幸运袋子,拿比x大的更不是,直接return count;