算法---杨辉三角来求数学的组合问题

版权声明:转载请注明来源 https://blog.csdn.net/tangyuan_sibal/article/details/88362694

有作死去做算法题,结果又遇到一道题目卡住了,题目是这个样子的:

小Q有X首长度为A的不同的歌和Y首长度为B的不同的歌,现在小Q想用这些歌组成一个总长度正好为K的歌单,每首歌最多只能在歌单中出现一次,在不考虑歌单内歌曲的先后顺序的情况下,请问有多少种组成歌单的方法。
输入描述:
每个输入包含一个测试用例。
每个测试用例的第一行包含一个整数,表示歌单的总长度K(1<=K<=1000)。
接下来的一行包含四个正整数,分别表示歌的第一种长度A(A<=10)和数量X(X<=100)以及歌的第二种长度B(B<=10)和数量Y(Y<=100)。保证A不等于B。
---->>输出描述:
输出一个整数,表示组成歌单的方法取模。因为答案可能会很大,输出对1000000007取模的结果。
示例1
---->>输入
5
2 3 3 3
—>>输出
9

当时我的思路是首先判断两种类型的歌词的长度相加刚好等于所要的歌单长度(也就是题目给的示例那样子),就直接相乘就可以了。此外不相等的时候,就要用循环来判断要多少首A型的和多少首B型的,这就涉及到组合了,也就是A型抽出i首和B型抽出j首的排列组合C(x,i)*C(y,j),当时以为很简单,马上要写代码,结果卡住了。。。这样是用循环,那不是好麻烦,而且自己是个菜鸡,还是写不出来,。。。。。这时候当然是去看看大佬的思想啦,看了好多基本是动态规划的思想,而作为一名标准的菜鸡对动态规划还不是很理解。看到下面一个用杨辉三角的,去理解了一下,简直不要太酷了(主要自己太菜,不知道杨辉三角的特性):杨辉三角上面,一个数等于它头顶的数加上头顶偏左一位的那个数的和
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1

而组合呢,根据数学归纳法又有C(x,i)=C(x-1,i)+C(x-1,i-1),这不是刚刚好是杨辉三角的公式吗,我的天,这思路。。。。真的深深对数学大佬折服。瞬间打通任通二脉(参照大佬思路),写下代码:


import java.util.Scanner;
public class Music {
	static long  c[][] = new long[105][105];
	static long mod = 1000000007;
	public static void main(String[] args) {
		
	Scanner scanner = new Scanner(System.in);
	while(scanner.hasNext())
	{
		int k = scanner.nextInt();
		int a = scanner.nextInt();
		int x = scanner.nextInt();
		int b = scanner.nextInt();
		int y = scanner.nextInt();
		
		init_yanghui();
		if(a!=b)
		{
			long sum = 0;
		for(int i=0;i<=x;i++)
		{
			for(int j=0;j<=y;j++)
			{
				//当相加大于k,后面就没必要再继续加了
			    if((a*i+b*j)>k)
					break;
				if((a*i+b*j)==k)
				{
					//采用杨辉三角计算c[x][i]
					sum+=(c[x][i]*c[y][j]);
				}

			}
		}
		System.out.println(sum%mod);
		}
		
	}
	}
	//初始化杨辉三角函数
	private static void init_yanghui() {
		
		c[0][0]=1;
		for(int i=1;i<100;i++)
		{
			c[i][0] = 1;
			for(int j=1;j<100;j++)
			{
				c[i][j] = (c[i-1][j]+c[i-1][j-1])%mod;
			}
		}
		
	}
}

猜你喜欢

转载自blog.csdn.net/tangyuan_sibal/article/details/88362694