首页 > 代码库 > 算法概述(无法编译)结果:除数是零(调试的结果)

算法概述(无法编译)结果:除数是零(调试的结果)

 

1)最大约数问题:

对于给定的两个正整数a,b,计算a和b之间约数个数最多的数。比如:a=1,b=36,1和36之间约数个数最多的是36,个数是9.

思路:普通的方法就是循环测试a和b之间每一个数到底有多少个约数,然后逐一比较

1第一次尝试:

int number=0;//统计约数的个数
int flag=0;//设置比较数,当后一个数的约数个数大于前一个数时,重置
for(int i=a;i<=b;i++)//外层循环从a到b
{
 //for(int j=0;j<=i;j++)//内层循环检测从1到自身

//修改为:

for(int i=1;j<=i;j++)//程序员总是以为自己不会犯这种低级错误

//在以后的生活中提醒自己肮脏的过去是为了迎接光明的未来
 {
  if(i%j==0)
  {
   number++;
  }
 }
 if(number>flag)//重置标志位
 {
  flag=number;
 }

   number=0;//刚才忘记恢复计数值为0
}

第二次尝试:在时间复杂度上,能否缩短运算的时间,通过观察发现,当内层循环运行到自身的一半,直到最后自身,才发现有一个约数存在,那就是它本身,例如:数字100,当超过50,51,52,53.。。。一直到99再也没有100的约数,我们通过修改上面的程序减少运算的复杂度,循环次数减少一半,在空间浮点数运算上面(在此,提醒读者本人水平有限,没有深入了解计算机如何进行除法运算的,请见谅)

所以程序修改如下:

int number=0;//统计约数的个数
int flag=0;//设置比较数,当后一个数的约数个数大于前一个数时,重置
for(int i=a;i<=b;i++)//外层循环从a到b
{
 for(int j=1;j<=i/2;j++)//内层循环检测从1到自身
 {
  if(i%j==0)
  {
   number++;
  }
 }
 number++;//自身也是一个约数,需添加进去
 if(number>flag)//重置标志位
 {
  flag=number;
 }
   number=0;//刚才忘记恢复计数值为0
}

现在基于上面的思想:1、如果这个数不能被2整除,范围会缩短一半

2.如果这个数也不能被3正确,范围接着变小

3.发现一个规律就是尝试用素数表里面的数去整除这个数,范围更加小了

且慢,我们以为已经到了极限,但是一个更大的问题来了:
只要它是偶数绝对会比奇数拥有更大的约数。当然了,我们需要考虑到a和b的范围,相邻的两个数之间偶数的约数的个数必然不会小于奇数的约数个数(除了1和2之外),例如:12和13,80和81,因此,这个条件成立下,循环次数将再一次下降一半。

第三次尝试:因此选择跳过奇数的测试直接比较两个偶数的约数个数,代码如下:

 

算法概述(无法编译)结果:除数是零(调试的结果)