poj_2109 二分+大整数乘法

思路:二分法+大整数乘法

已知n,p,求k^n=p中的k。

知道n,p,则k的位数可以确定。假设为k为4位,则从1000至9999用二分查找逼近k,试探一个数的n次幂时用大整数乘法来做,直到得到那个k。


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

char p[110];
int res[110] = { 0 }, resTemp[110] = {0};
int n, k_digits=0,p_digits=0;

void mutiply(int *a, int *b)
{
	int i, j;
	for (i = 0; i < 110; i++)
	{
		for (j = 0; j < 10; j++)
		{
			res[i+j] += a[i] * b[j];
		}
	}
	for (i = 0; i < 110; i++)
	{
		res[i + 1] += res[i] / 10;
		res[i] = res[i] % 10;
	}
}

int func(int mid, int n)
{
	int i=0;
	int k[10] = { 0 }, temp[110] = {0};
	//change mid->k from int to int*
	while (mid!=0)
	{
		k[i] = mid % 10;
		temp[i] = k[i];
		mid = mid / 10;
		i++;
	}
	//mutiply k n times
	while ((n-1) != 0)
	{
		mutiply(temp,k);
		for (i = 0; i < 110; i++)
		{
			temp[i] = res[i];
			res[i] = 0;
		}
		n--;
	}
	//reverse p 
	for (i = 0; i < 110; i++)
	{
		resTemp[i] = 0;
	}
	for (i = p_digits-1 ; i>=0; i--)
	{
		resTemp[p_digits - i-1] = p[i]-'0';
	}
	//compare temp and resTemp
	bool flag = false;
	for (i = 110-1; i >=0 ; i--)
	{
		if (resTemp[i]>temp[i])
		{
			flag = true;
			return -1;
		}
		else if (resTemp[i] < temp[i])
		{
			flag = true;
			return 1;
		}
	}
	if (flag == false)
	{
		return 0;
	}
}

int main()
{
	// k^n=p
	int i,mid,min,max;
	bool finish = false;
	while (cin >> n >> p)
	{
		finish = false;
		//identify the k's digits
		for (i = 0; i < 110 && p[i] != '\0'; i++)
			;
		p_digits = i;
		k_digits = (int)ceil((double)i / n);
		for (i = 1, min = 1, max = 9; i < k_digits; i++)
		{
			min *= 10;
			max *= 10;
			max += 9;
		}
		//binary search k
		while (!finish)
		{
			mid = (min + max) / 2;
			if (min > max)
			{
				break;
			}
			int ans = func(mid,n);
			switch (ans)
			{
				case -1:
					min = mid + 1;
					break;
				case 0:
					finish = true;
					break;
				case 1:
					max = mid - 1;
					break;
			}//end switch
		}//end binary search
		cout << mid << endl;
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值