Chinaunix首页 | 论坛 | 博客
  • 博客访问: 912492
  • 博文数量: 299
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 2493
  • 用 户 组: 普通用户
  • 注册时间: 2014-03-21 10:07
个人简介

Linux后台服务器编程。

文章分类

全部博文(299)

文章存档

2015年(2)

2014年(297)

分类: C/C++

2014-07-30 09:45:35

转载请注明出处,声明如下:

作者:peizhongyou

原文地址:

前几天参加一个编程竞赛,涉及到部分位运算的知识,准备不足挂了。事后在网上搜了一下位运算的介绍看到《位运算之美》这篇博客,其中提到了一个题目“不许用%和/来实现求任意数除以3的余数”感觉挺有意思,可惜博文中没有介绍方法,没办法只能自己解决了,解决方法如下:

第一种方法:循环减法

如果不用位运算,我们可以用一种最笨拙的方法,每次减3,直到小于3为止,剩多少自然是余数了(-_-)。

第二种方法:位运算递归求解

这种方法我们首先要分析一下,在什么情况下数字才能被3整除?整数表示时,我们都知道数字相加为3的倍数时可以被3整除,那么二进制表示时呢?

这里需要用到二项式定理中的一些知识了,我们知道

其中前m-1项都是可以被3整除的,余数项既是(-1)^m项,所以我们可以用一个余数项r来记录余数项的值,所以对于给定的整数a,我们只需要统计a二进制表示中1的位置即可,当1位于偶数位时那么余项为r-1(注意二进制表示从2^0开始),1在奇数位的时候余数项r+1,然后判定r的绝对值是否在3的范围内,如果还是大于3则迭代调用该过程,具体算法如下:

(1)判定整数a的符号,若a为负,则将a转化为正处理,并记录a的正负号;

(2)每次将a向右移动一位,判断a&1的值是否为1,并判定该位置的奇偶性(r&1),若为奇数则r+1,否则r-1;

(3)根据a的正负号做调整,若a为负值,则r = -r,判定|r|<3,若满足,当r>=0时返回r,若r<0时,返回r+3;

(4)若r>3,则重复1-3步,直到程序结束。

程序代码如下:

int divisorByThree(int a)

{

      bool mark(false);//用于标示出a是正数还是负数,是负数则为true

      int i(0);

      int even(0);

      int remainder(0);


      if (a < 0)

      {

         mark = true;

         a = -a;

      }


      do 

      {

         if ((a&1)==1)//说明末尾位是1

         {

            even++;

            if ((even&1)==1)//说明1出现在奇数位上,这剩余值为正

            {

               remainder += 1;

            }

            else

           {

              remainder -=1;

           }

        }

       else

      {

          even++;

      }

       a >>=1;

      } while (a);


      if (mark)

      {

          remainder = -remainder;

      }

      if (abs(remainder)<3)//剩余值小于3,说明有可能被整除,或者剩余1或2

     {

          return (remainder>=0)?remainder:(remainder+3);

      }

      else

      {

          divisorByThree(remainder);

      }

}

阅读(2162) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~