TopCoder——Lottery(买彩票问题)

Problem Statement
In most states, gamblers can choose from a wide variety of different lottery games. The rules of a lottery are defined by two integers (choices and blanks) and two boolean variables (sorted and unique). choices represents the highest valid number that you may use on your lottery ticket. (All integers between 1 and choices, inclusive, are valid and can appear on your ticket.) blanks represents the number of spots on your ticket where numbers can be written.
The sorted and unique variables indicate restrictions on the tickets you can create. If sorted is set to true, then the numbers on your ticket must be written in non-descending order. If sorted is set to false, then the numbers may be written in any order. Likewise, if unique is set to true, then each number you write on your ticket must be distinct. If unique is set to false, then repeats are allowed.
Here are some example lottery tickets, where choices = 15 and blanks = 4:
{3, 7, 12, 14} -- this ticket is unconditionally valid.
{13, 4, 1, 9} -- because the numbers are not in nondescending order, this ticket is valid only if sorted = false.
{8, 8, 8, 15} -- because there are repeated numbers, this ticket is valid only if unique = false.
{11, 6, 2, 6} -- this ticket is valid only if sorted = false and unique = false.
Given a list of lotteries and their corresponding rules, return a list of lottery names sorted by how easy they are to win. The probability that you will win a lottery is equal to (1 / (number of valid lottery tickets for that game)). The easiest lottery to win should appear at the front of the list. Ties should be broken alphabetically (see example 1).

简单来说,题目就是问给N个可选数字,M个空白,在有些一限制的情况下(是否允许重复,是否要求有序)共有多少种组合方式?

允许重复,不要求有序: N^M

不能重复,不要求有序:N(N-1)(N-2)...(N-M+1)

不能重复,但必须有序:N(N-1)(N-2)...(N-M+1)/M!

允许重复,但必须有序:?

这个貌似就没那么简单了,我是没想到如何通过组合数学方式直接得出答案,不过可以通过递归求解。因为必须有序,所以第i位的数字一定要大于等于第i-1位。定义递归函数f(m,n)为在第m位能填数字n的可能组合数,它等于在第m-1位填数字1到n的组合数之和。即f(m,n)=f(m-1,1)+f(m-1,2)+...+f(m-1,n). 我没要求的就是f(M,N)

public class Lottery {

	//不能重复,不要求有序
	private long factorial(int n, int size)
	{
		long sum=1;
		for(int i=0;i<size;i++)
		{
			sum*=(n-i);
		}
		return sum;
	}
	//允许重复,不要求有序
	private long pow(int n, int size)
	{
		long sum=1;
		for(int i=0;i<size;i++)
		{
			sum*=n;
		}
		return sum;
	}
	//不能重复,但必须有序
	private long combination(int n, int m)
	{
		return factorial(n,m)/factorial(m,m);
	}
	
	long table[][]=new long[100][10];
	//允许重复,但必须有序
	private long combinationNoUnique(int n, int m)
	{
		for(int i=0;i<n;i++)
			Arrays.fill(table[i],-1 );
		return f(m,n);
	}
	
	//在第m位能填数字n的可能组合数=在第m-1位填数字1到n的组合数之和
	private long f(int m,int n)
	{
		if(m==0)
			return 1;
		if(table[n-1][m]!=-1)
			return table[n-1][m];

		long sum=0;
		for(int i=1;i<=n;i++)
		{
			sum+=f(m-1,i);
		}
		table[n-1][m]=sum;
		return sum;
	}
	
	public static void main(String args[])
	{
		Lottery lot=new Lottery();
		System.out.println(lot.combinationNoUnique(93, 8));
	}

}


你可能感兴趣的:(TopCoder——Lottery(买彩票问题))