当时没有做出来,现在写一写思路。
题目:
现有n个人,要从这n个人中选任意数量的人组成一只队伍,再在这些人中选出一名队长,求不同的方案对10^9+7取模的结果。如果两个方案选取的人的集合不同或选出的队长不同,则认为这两个方案是不同的。
分析:
因为选择过程与顺序无关,从n个不同元素中取出m个元素的组合数为c(n,m)。则总的方案数为
1 * C(n,1)+2 * C(n,2)+3 * C(n,3)+4 * C(n,4)+…n * C(n,n)
方案一:
学习了网友的思路,具说根据数学公式推导,最终上面组合式结果为n2^(n-1)。(我没推出来,可能涉及到下面泰勒展开式)
思路:因此问题转化为求 n2^(n-1)。为了降低时间复杂度可用 快速幂 的方法计算 ,我的代码如下:
import java.util.Scanner;
/**
* Created by fangjiejie on 2020/3/23.
*/
public class Title1 {
static int mod = 1000000007;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int res = n * MyPower(2, n - 1);
System.out.println(res % mod);
}
public static int MyPower(int a, int b) {
int level = a;
int result = 1;
while (b != 0) {
if ((b & 1) == 1) {
result = result * level % mod;
}
level = level * level % mod;
b = b >> 1;
}
System.out.println(result);
return result % mod;
}
}
方案二:
在复习组合数的过程中,我发现另一种求解方法。但在网上没有看到有人用这种方法做,所以不确定是否可以AC
用到的两个公式计算:
-
公式一: C(n,m)=C(n-1,m-1)+C(n-1,m)
-
公式二:
思路:动态规划。用公式一来计算 每一个C(n,m),并保存下来,以供后续计算使用,空间换时间。注意处理好初始值。我的代码如下:
class Main {
static int mod = 1000000007;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int C[][] = new int[n + 1][n + 1];//C[i][j]存储着C(i,j)的值
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
if (j == i) C[i][j] = 1;//i==1&&j==1
else if (j == 1) C[i][j] = i;
else C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % mod;
}
}
int sum = 0;
for (int i = 1; i <= n; i++) {
sum = (sum + i * C[n][i]) % mod;
}
System.out.println(sum);
}
}