清华大学考研复试机试:root(N,k)

版权声明:本文为博主原创,未经博主允许不得转载。转载请附上原文链接。 https://blog.csdn.net/qq_38341682/article/details/88583289

题目描述

N<k时,root(N,k) = N,否则,root(N,k) = root(N’,k)。N’为N的k进制表示的各位数字之和。输入x,y,k,输出root(x^y,k)的值 (这里^为乘方,不是异或),2=<k<=16,0<x,y<2000000000,有一半的测试点里 x^y 会溢出int的范围(>=2000000000)

输入描述

每组测试数据包括一行,x(0<x<2000000000), y(0<y<2000000000), k(2<=k<=16)

输出描述

输入可能有多组数据,对于每一组数据,root(x^y, k)的值

示例:

输入

4 4 10

输出

4

分析

这道题乍一看好像没有什么思路,那就先暴力求解试试。不过不管你用pow函数,还是用快速幂运算,都过不了,因为结果已经爆long long int。有关快速幂运算这里简单提一下,不清楚的可以自行Google。

快速幂运算是用来计算形如xy这种式子的一种快速方法,核心在于将指数y表示为二进制的形式,并将计算拆分为x2n这种形式,这样在计算后一个指数运算时,可以利用前面的计算结果,减少了计算量,加快了运算速度。

这道题暴力解决不了,只能想其他方法,考虑到这可能是一个数学问题,如果我们能够找出其中的规律,就能迎刃而解。题目说N’是N的k进制数字之和,那么可以首先将N用k进制表示出来。

设a0,a1,…,an分别为kn的系数
那么N = a0 + a1k + a2k2 + … + ankn
根据题意N’ = a0 + a1 + … + an,两式相减
N - N’ = a1(k-1) + a2(k2-1) + … + an(kn-1),两边同时模k-1
N - N’ % (k-1) = 0,继续递推下去
N’ - N’’ % (k-1) = 0,

N(i-1) - N(i) % (k-1) = 0,进行累加
N - N(i) % (k-1) = 0,移项
N(i) = N % (k-1),N(i)即为我们所求值,N(i) < k
上面的推导过程使用了模运算的性质,如果有不清楚的地方,可以学习一下模运算。模运算在数学题中很常见,也需要掌握。

这样我们就得到了上面的公式,因为在运算过程中取模,所以不会爆int。另外还需要注意边界条件,N(i) = 0的情况下,实际应该输出k-1。因为如果xy不为0,那么结果一定不会为0。在实际编程中使用了快速模幂运算,其实就是在快速幂运算的基础上进行改进,在每一步的运算过程中都进行取模运算,这个算法也是需要掌握的。

AC代码如下:

#include<iostream>

using namespace std;

int func(long long int x, long long int y, int k)//快速模幂运算模板
{
	int result = 1;
	while(y > 0)
	{
		if(y&1)//取y二进制的最低位
		{
			result = (result*x) % k;
		}
		x = (x*x) % k;//每次需要增大基数
		y >>= 1;//y右移一位,相当于除以2
	}
	return result;
}

int main(void)
{
	int x, y, k;
	while(cin >> x >> y >> k)
	{
		int result = func(x, y, k-1);//模为k-1
		if(result == 0)//边界条件处理
		{
			cout << k-1;
		}
		else
		{
			cout << result;
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_38341682/article/details/88583289