分享一个用动态规划求解幂的算法

threenewbee 2015-03-30 04:27:23
加精
原问题在http://ask.csdn.net/questions/171941

我的解答
// ConsoleApplication1.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include <iostream>
#define QTMAX 40

using namespace std;

int lenqt(int qt[])
{
for (int i = QTMAX - 1; i >= 0; i--)
{
if (qt[i]) return i + 1;
}
return 0;
}

double mypow(int x, int y)
{
int yy = y;
int qt[QTMAX];
double qr[QTMAX];
for (int i = 0; i < QTMAX; i++) qt[i] = 0;
int idx = 0;
while (yy > 0)
{
qt[idx++] = yy % 2;
yy /= 2;
}
double xx = (double)x;
qr[0] = xx;
for (int i = 1; i < lenqt(qt); i++)
{
qr[i] = qr[i - 1] * qr[i - 1];
}
double r = 1.0;
for (int i = 0; i < lenqt(qt); i++)
{
if (qt[i])
{
r *= qr[i];
}
}
return r;
}

double slowpow(int x, int y)
{
double r = x;
for (int i = 1; i < y; i++)
r *= (double)x;
return r;
}

int _tmain(int argc, _TCHAR* argv[])
{
cout << mypow(1, 2100000000) << endl;
cout << slowpow(1, 2100000000) << endl;
return 0;
}


C++不是我熟悉的编程语言,只是提问者要求用C++,勉为其难回答下,抛砖引玉
...全文
2658 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
_明月 2016-03-02
  • 打赏
  • 举报
回复
谢谢分享,点个赞。
gotopause 2015-04-14
  • 打赏
  • 举报
回复
我有代码恐惧症,看不下去代码啊,你们写的都是啥啊
程序员鼓励师 2015-04-11
  • 打赏
  • 举报
回复
laoer_2002 2015-04-08
  • 打赏
  • 举报
回复
谢谢楼主分享!
u010227315 2015-04-07
  • 打赏
  • 举报
回复
用快速幂确实是个更简单的方法
罗博士 2015-04-06
  • 打赏
  • 举报
回复
快速幂就够了。又简单又快速。
無銘- 2015-04-06
  • 打赏
  • 举报
回复
看看.....
一根烂笔头 2015-03-30
  • 打赏
  • 举报
回复
最初的想使用归并思想,发现y不一定构成完全二叉树
一根烂笔头 2015-03-30
  • 打赏
  • 举报
回复
自己实现了一个,但是发现楼上已经做完了,而且雷同,不过相对楼上,我考虑的更多一些,不管好坏,贴出来吧

#include <stdio.h>
#include <stdlib.h> 
/*思想:把y展开成2幂次多项式之和
  比如:5 = 1 + 4; 11 = 1 + 2 + 8 
  原理就是二进制转十进制的过程
  x^11 = x^(1 + 2 + 8) = x^1 * x^2 * x^8
  =>(x^11) % p = ((x^1 % p) * (x^2 % p) * (x^8 % p)) % p
  迭代求解即可
 */

void mod(void)
{
	int i ;
	unsigned long long interm_val[32] = {0};
	unsigned long long x, y;
	unsigned long long m = 1000000007L;
	unsigned long long tmp;
	unsigned long long res;

	scanf("%lld %lld", &x, &y); //不针对此题,只阐述思想
	if(x < 2 || y < 2 || x > m || y > m) { //简单的安检
		printf("Usage: input value should within [2, 10^9]");
		exit(0);
	}

	interm_val[0] = x;//初始化
	i = 0; //计数器
	res = 1; //结果
	while(y) {
		if(y & 0x1) {
			res *= interm_val[i];
			if(res > m)
				res %= m;
		}

		tmp = interm_val[i] * interm_val[i];
		/*m约等于10^9,m*m不到10^19,没有超过ULL的范围
		 *因此存储中间结果的数组可以简化。数组是为处理越界问题而设计的
		 *假设相乘越界,那么就不能直接相乘,需要用低维数组中的中间结果
		 *进行相乘处理。假设上面越界,那么换成
			tmp = ((interm_val[i] * interm_val[i - 1])%p * interm_val[i - 1])%p;
			尝试,还不行则继续降维
			tmp = (((((interm_val[i] * interm_val[i - 1])%p * interm_val[i - 2])%p) *
				interm_val[i - 2])%p * interm_val[i - 2])%p;
			或
			tmp = ((((interm_val[i] * interm_val[i - 2])%p * interm_val[i - 2])%p *
				interm_val[i - 2])%p * interm_val[i - 2])%p;
			以此继续,直到不越界情况下相乘
			这个过程可以写成一个处理函数
			不过这里不需要了,多提一点而已!
		*/
		if(tmp > m)
			tmp %= m;
		interm_val[i + 1] = tmp;

		y >>= 1;
		++i;
	}

	printf("%lld\n", res);

}

int main(int argc, char *argv[])
{
	mod();
	exit(0);
}
threenewbee 2015-03-30
  • 打赏
  • 举报
回复
引用 1 楼 u012436960 的回复:

#define MOD 1000000007
// a^x
unsigned long long pow(unsigned long long a,unsigned long long x)
{
    unsigned long long result=1;
    a%=MOD;
    while(x)
    {
        if(x&1)
            result=(result*a)%MOD;
        a=(a*a)%MOD;
        x>>=1;
    }
    return result;
}
这样如何?
赞,思路和我类似,代码简洁。
u012436960 2015-03-30
  • 打赏
  • 举报
回复

#define MOD 1000000007
// a^x
unsigned long long pow(unsigned long long a,unsigned long long x)
{
    unsigned long long result=1;
    a%=MOD;
    while(x)
    {
        if(x&1)
            result=(result*a)%MOD;
        a=(a*a)%MOD;
        x>>=1;
    }
    return result;
}
这样如何?

7,540

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 VC.NET
社区管理员
  • VC.NET社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧