zoukankan      html  css  js  c++  java
  • 两个例题

    一、计算组合数。编写函数,参数是两个非负整数n和m,返回组合数 ,其 中m≤n≤25。例如,n=25,m=12时答案为5200300。

    【分析】 既然题目中的公式多次出现n!,将其作为一个函数编写是比较合理的:

    long long factorial(int n){

      long long m = 1;

       for(int i = 1; i <= n; i++) m *= i;

       return m; }

    long long C(int n, int m) {

      return factorial(n)/(factorial(m)*factorial(n-m)); }

    提示:即使最终答案在所选择的数据类型范围之内,计算的中间结果仍然可能溢出。

    当n=21,m=1的返回值是-1,溢出。

    解决方法:约分。

    一个简单的方法是利用n!/m!=(m+1) (m+2)…(n-1)n。虽然不能完全避免中间结果溢出,但是对于题目给出的范围已经可以保证得到正确的结果了。

    long long C(int n, int m) {

      if(m < n-m) m = n-m;

      long long ans = 1;

      for(int i = m+1; i <= n; i++) ans *= i;

      for(int i = 1; i <= n-m; i++) ans /= i;

    return ans; }

    小技巧:当m<n-m时把m变成n-m。作用:进一步降低复杂度。

    二、素数判定。编写函数,参数是一个正整数n,如果它是素数,返回1,否则返回0。

    【分析】 根据定义,被1和它自身整除的、大于1的整数称为素数。

    //n=1或者n太大时请勿调用

    int is_prime(int n) {

      for(int i = 2; i*i <= n; i++)

        if(n % i == 0) return 0;

    return 1; }

    小技巧:注意这里用到了两个小技巧。一是只判断不超过sqrt(x)的整数i。二 是及时退出:一旦发现x有一个大于1的因子,立刻返回0(假),只有最后才返回1(真)。 函数名的选取是有章可循的,“is_prime”取自英文“is it a prime?”(它是素数吗?)。

    注意代码上方提示:太小是考虑 1 ,太大是考虑i*i会溢出。

    改进版:

    int is_prime(int n) {

      if(n <= 1) return 0;

      int m = floor(sqrt(n) + 0.5);

      for(int i = 2; i <= m; i++)

        if(n % i == 0) return 0;

    return 1; }

    除了特判n≤1的情况外,程序中还使用了变量m,一方面避免了每次重复计算sqrt(n),另 一方面也通过四舍五入避免了浮点误差——正如前面所说,如果sqrt将某个本应是整数的值 变成了xxx.99999,也将被修正,但若直接写m = sqrt(n),“.99999”会被直接截掉。

    注:为什么只需要计算到开平方就可以?

    https://blog.csdn.net/LZXloveGYD/article/details/71340090

  • 相关阅读:
    inner join on, left join on, right join on讲解(转载)
    ref 与 out
    Shell基础01
    Python 基础01
    linux基础03
    Shell基础02
    linux基础02
    Linux基础01
    linux基础05
    linux基础04
  • 原文地址:https://www.cnblogs.com/LOW-ctfer/p/10387617.html
Copyright © 2011-2022 走看看