阿里笔试2020.3.23 第一题

当时没有做出来,现在写一写思路。
题目:
现有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)。(我没推出来,可能涉及到下面泰勒展开式)
在这里插入图片描述
思路:因此问题转化为求 n
2^(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);
    }
}
发布了184 篇原创文章 · 获赞 60 · 访问量 16万+

猜你喜欢

转载自blog.csdn.net/StubbornAccepted/article/details/105264073