求1+2+…+n(要求不能使用乘除法、for、while、if、else、switch、case等关键字)

这篇博客探讨了一种巧妙地使用递归算法来计算1到n的和,避免使用乘除法、for、while、if等关键字。通过递归和位操作实现,同时还分享了其他几种创新的解决方案,包括利用逻辑与的特性以及类的静态变量。
摘要由CSDN通过智能技术生成
要求不能使用乘除法、for、while、if、else、switch、case等关键字以及条件判断语句(A?B:C)。

其实会有很多种解法,但是下面给出了一个简单的代码-----巧用递归算法

[cpp]  view plain  copy
 print ?
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <string.h>  
  4.   
  5. int add_fun(int n, int & sum)  
  6. {  
  7.     n && add_fun(n-1, sum);  
  8.       
  9.     return (sum += n);  
  10. }  
  11.   
  12. int main()  
  13. {  
  14.     int sum = 0;  
  15.     int n = 100;  
  16.   
  17.     printf("1+2+...+n = %d\n", add_fun(n, sum));  
  18.   
  19.     return 0;  
  20. }  


















~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`

看到这个问题,第一个反应是真变态啊。 然后,直觉是不能用循环就只能用递归了。可递归怎么跳出来却遇到了麻烦, 我连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\n",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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值