从自幂数计算谈算法优化方法

第一章  前言


1.1  参考文献

       郭继展,郭勇,苏辉《程序算法与技巧精选》,机械工业出版社,2008年5月第一版,ISBN 978-7-111-23816-4,第7.3节:求自幂数——用数组预作乘法提高速度100倍。


1.2  写此文章的目的

       (1)想用自己的语言总结书上的内容;

       (2)用自己的笔记本电脑测试下各个方法间,效率差距究竟有多大;

       (3)用自己的风格写一遍代码,加深对知识的理解,也方便以后自己复习。


1.3  自幂数定义

        http://b.baidu.cn/view/8059450.htm

1.4  文章概述

       我会先在第二章讨论各种算法的效率问题,并贴所有源代码供读者验证,也对结果进行截图方便不愿跑代码的懒读者快速读完本篇文章。在第三章写一段计算所有自幂数的小程序。

       PS:本来排版很好的,涉及到英文的书写时,博客给我自动换行换到难看死了……


第二章  算法之间的差距


2.1  最原始的思路

       把pow(10,x-1)至pow(10,x)内的所有数遍历一遍,来求x位自幂数,。
#include <iostream>
#include <cmath>
#include <ctime>
using namespace std;

clock_t start__;
#define tic start__=clock()
#define toc cout<<(clock()-start__)*1000/CLOCKS_PER_SEC<<"ms\n"

void zms1(int x)	// 自幂数拼音首字母:zms,后缀+数字用于区别不同算法的zms函数
{
	int l=pow(10,x-1),r=pow(10,x),i,i0,j,t,a;
	for(i=l; i<r; i++)
	{
		i0 = i;	// 拷贝i的一个副本
		for(t=j=0;j<x;j++)
		{
			a = i0%10; // 得到最末位的值 
			t += a*pow(10,j)-pow(a,x);
			i0 /= 10;
		}
		if(t==0) cout<<i<<endl;
	}
}

int main()
{
	tic,zms1(7),toc;
	return 0;
}



2.2  用各个位的分别穷举代替一个值的穷举

       因为算法涉及到一个值各个位上的操作,每次需要进行a=i0%10; i0/=10;等操作。以七位自幂数为例,我们不妨穷举7个位上的每个值来求解。当然,这样的弊端是,函数的清晰度会降低,也无法像zms1一样具有通用性——可以通过输入参数x,求任意x位的自幂数。优点是降低循环内部的操作次数,效率会提升。我单写一个七位自幂数的函数zms2来验证。

#include <iostream>
#include <cmath>
#include <ctime>
using namespace std;

clock_t start__;
#define tic start__=clock()
#define toc cout<<(clock()-start__)*1000/CLOCKS_PER_SEC<<"ms\n"

void zms2()
{
	int i,j,k,l,m,n,o;	//用来穷举各个位的值的变量,即值本身为ijklmno
	for(i=1;i<10;i++) for(j=0;j<10;j++) for(k=0;k<10;k++)
		for(l=0;l<10;l++) for(m=0;m<10;m++) for(n=0;n<10;n++) for(o=0;o<10;o++)
		{
			if(pow(i,7)+pow(j,7)+pow(k,7)+pow(l,7)+pow(m,7)+pow(n,7)+pow(o,7)
				==1000000*i+100000*j+10000*k+1000*l+100*m+10*n+o)
				cout<<i<<j<<k<<l<<m<<n<<o<<endl;
		}
}

int main()
{
	tic,zms2(),toc;
	return 0;
}


       zms2中,判断一个数是否为自幂数的方法如if语句中所写的式子,非常清晰易懂。而zms1中方法换汤不换药,在数学里,要判断两个表达式f(x)与g(x)是否相等,可以定义h(x)=f(x)-g(x),如果h(x)恒等于0,则f(x)=g(x)。此处道理相同,相当于用t来存储右式1000000*i+100000*j+10000*k+1000*l+100*m+10*n+o减去左式pow(i,7)+pow(j,7)+pow(k,7)+pow(l,7)+pow(m,7)+pow(n,7)+pow(o,7)的值,如果结果为t==0,则为七位自幂数。在后续的程序中,我们主要使用zms1的自幂数判断方法,用这种方法才能方便的存储中间计算值和进行回溯运算。
       再回到zms1和zms2的效率分析上,zms2因为少了对原值各个位的拆解运算,效率提高了1倍多。

2.3  事先存储中间运算量

       再仔细分析语句:pow(i,7)+pow(j,7)+pow(k,7)+pow(l,7)+pow(m,7)+pow(n,7)+pow(o,7)==1000000*i+100000*j+10000*k+1000*l+100*m+10*n+o,因为i,j...o只能取0~9的值,在计算pow(?,7)方面,只有10种运算——pow(0,7),pow(1,7),pow(2,7)...pow(9,7)。这意味着什么呢?在zms2进行的7*(1千万-1百万)=6300万次运算中,跑的7次幂部分,其实只有10种结果!相当于一套10道题的试卷,让你重复做630万次!!!在pow(10,?)中,也是一样的道理。
       于是,我们就想到&
  • 7
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值