zoukankan      html  css  js  c++  java
  • 【编程题目】求1+2+…+n, 要求不能使用乘除法、for、while、if、else、switch、case和条件语句

    看到这个问题,第一个反应是真变态啊。 然后,直觉是不能用循环就只能用递归了。可递归怎么跳出来却遇到了麻烦, 我连goto语句都考虑了也没弄好。

    后来想到一个非常NC的方法:查找表。 如果n限定一个比较小的范围直接用查找表好了。 但题目的目的肯定不是这样的.....

    后来,我转换了一下思路 1+2...+n = (n*n + n)>>1  只要求出n*n来就好了, 但问题是不能用乘法,于是硬件出身的我想到了二进制&,|,>>,<<都是可以用的。

    思路设n = 5 则 n = 1 0 1 b.  n * n =

                1 0 1

    *          1 0 1

    --------------------

               1 0 1         5

            0 0 0

         1 0 1                20

    --------------------- 

         1 1 0 0 1         25

    我们只要把中间那一段的数求出来,加起来就好了。 代码实现中,因为不能写for,我又懒得自己写太多遍加法,于是设定n的取值范围只能是 0-255

    /*
    题目: 计算 1+2+3+...+n
    要求:不可用 乘除 if else for while switch case ?:
    */
    #include <stdio.h>
    
    const unsigned char b[16] = {1, 1<<1, 1<<2, 1<<3, 1<<4, 1<<5, 1<<6, 1<<7, 1<<8, 1<<9, 1<<10, 1<<11, 1<<12, 1<<13, 1<<14, 1<<15};
    
    int get_add_factor(unsigned char n, unsigned char onebit)
    {
         unsigned char b = onebit + (onebit<<1) + (onebit<<2) + (onebit<<3) + (onebit<<4) + (onebit<<5) + (onebit<<6) + (onebit<<7);
         return n&b;
    }
    
    int addn(unsigned char n)
    {
        unsigned char bits[8] = {n&b[0], (n&b[1])>>1, (n&b[2])>>2 ,(n&b[3])>>3, (n&b[4])>>4, (n&b[5])>>5, (n&b[6])>>6, (n&b[7])>>7};  //把数字的每一位取出来
        int tmp[8] = {get_add_factor(n, bits[0]), get_add_factor(n, bits[1])<<1, get_add_factor(n, bits[2])<<2, get_add_factor(n, bits[3])<<3,
                      get_add_factor(n, bits[4])<<4, get_add_factor(n, bits[5])<<5, get_add_factor(n, bits[6])<<6, get_add_factor(n, bits[7])<<7};
    
        int pow = tmp[0] + tmp[1] + tmp[2] + tmp[3] + tmp[4] + tmp[5] + tmp[6] + tmp[7];
        int ans = (pow + n) >> 1;
        return ans;    
    }
    
    int main()
    {
        //addn 的输入必须是 0 - 255
        int r = addn(255);
    
        return 0;
    }

    然后,到网上看看别人的答案,我震惊了。原来有这么多种方法啊。

    最让我叹服的是下面这个版本: 利用逻辑与&&的特性 成功跳出了循环

    #include <stdio.h>  
    #include <stdlib.h>  
    #include <string.h>  
      
    int add_fun(int n, int &sum)  
    {  
        n && add_fun(n-1, sum);  //逻辑与 先计算左边的值 如果 左边的值不为真 则不会计算右边
        return (sum+=n);  
    }  
      
    int main()  
    {  
        int sum=0;  
        int n=100;  
      
        printf("1+2+3+...+n=%d
    ",add_fun(n, sum));  
      
        return 0;  
    } 

    方法三:利用类的静态变量 在构造函数中对静态变量做加法 构建多个类对象实现求和

    #include <iostream>
    using namespace std;
    
    class Temp
    {
    public:
        Temp()
        {
            N++;
            SUM+=N;
        }
        static int GetSum()
        {
            return SUM;
        }
        static void Reset()
        {
            N = 0;
            SUM = 0;
        }
        ~Temp(){};
    private:
        static int N;
        static int SUM;
    }; //注意分号 别忘了
    
    //初始化类的静态成员变量
    int Temp::N = 0;
    int Temp::SUM = 0;
    
    int Sum(int n)
    {
        Temp::Reset();
        Temp * a = new Temp[n];
        delete [] a;
        
        return Temp::GetSum();
    }
    int main()
    {
        int a = Sum(100);
        return 0;
    }

    方法四 利用函数指针.也是非常的巧妙 定义了一个函数指针的数组 只有i = 0的时候 !!i = 0, 其他情况下  !!i = 1 利用这个规则跳出递归

    #include <iostream>  
    using namespace std;  
      
    typedef int (*fun)(int);  
      
    int solution_f1(int i)  
    {  
        return 0;  
    }  
    
    int solution_f2(int i)  
    {  
        fun f[2]={solution_f1, solution_f2};  
        return i+f[!!i](i-1);  
    }  
      
    int main()  
    {  
        cout<<solution_f2(100)<<endl;  
        return 0;
    } 

    还有个方法五 利用虚函数的 具体思想其实跟 函数指针很像  这个没仔细看 因为我虚函数学得不好....

    #include <iostream>  
    using namespace std;  
      
    class A;  
    A* Array[2];  
      
    class A  
    {  
    public:  
        virtual int Sum(int n)  
        {  
            return 0;  
        }  
    };  
      
    class B:public A  
    {  
    public:  
        virtual int Sum(int n)  
        {  
            return Array[!!n]->Sum(n-1)+n;  
        }  
    };  
      
    int solution2_Sum(int n)  
    {  
        A a;  
        B b;  
        Array[0]=&a;  
        Array[1]=&b;  
      
        int value=Array[1]->Sum(n);  
     
        return value;  
    }  
      
    int main()  
    {  
        cout<<solution2_Sum(100)<<endl;  
        return 0;  
    }
  • 相关阅读:
    fedora上部署ASP.NET——(卡带式电脑跑.NET WEB服务器)
    SQL Server 请求失败或服务未及时响应。有关详细信息,请参见事件日志或其它适合的错误日志
    8086CPU的出栈(pop)和入栈(push) 都是以字为单位进行的
    FTP 服务搭建后不能访问问题解决
    指定的 DSN 中,驱动程序和应用程序之间的体系结构不匹配
    Linux 安装MongoDB 并设置防火墙,使用远程客户端访问
    svn Please execute the 'Cleanup' command. 问题解决
    .net 操作MongoDB 基础
    oracle 使用绑定变量极大的提升性能
    尝试加载 Oracle 客户端库时引发 BadImageFormatException。如果在安装 32 位 Oracle 客户端组件的情况下以 64 位模式运行,将出现此问题。
  • 原文地址:https://www.cnblogs.com/dplearning/p/3884910.html
Copyright © 2011-2022 走看看