题目描述
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)的值
示例1
输入
复制
4 4 10
输出
复制
4
解题解析:
对于root(N, k)中的N,我们可以把N看作关于k的多项式,也就是N = a0 + a1*k + a2*k^2 + … + an* k^n,而我们要求的root函数就是这个多项式的系数和,也就是a0 + a1 + a2 + ... + an。下面我们考虑root(N^2, k)。此时N^2 = (a0 + a1*k + a2*k^2 + … + an* k^n)^2,而这个多项式展开后的系数和是(a0 + a1 + a2 + … + an)^2,这个结果刚好就是先对N取root函数再平方的结果。实际上,我们很容易就能看出,多项式先乘方再取系数和(先乘再去掉k)与先取系数和再乘方(先去掉k再乘),结果是一样的(因为有没有k并不影响系数间的相乘,也不影响相乘之后的求和),于是乎,我们可以得到以下的递推公式:
root(x, y, k) = root((root(x, y / 2, k))^2, 1, k), y为偶数
root(x, y, k) = root((root(x, y / 2, k))^2 * root(x, 1, k), 1, k), y为非1的奇数
root(x, 1, k) = x % k + x / k % k + ...(大于k的话再重复求root)
有了递推关系之后,我们就可以直接写出一个O(log n)的递归解法了
代码实现:
#include <iostream>
using namespace std;
int root(int x, int y, int k)
{
if (y == 1) {
if (x < k)
return x;
else {
while (x >= k) {
int sum = 0;
while (x > 0) {
sum += x % k;
x /= k;
}
x = sum;
}
return x;
}
}
else {
int result = root(x, y / 2, k);
result *= result;
if (y % 2 == 1)
result *= root(x, 1, k);
return root(result, 1, k);
}
}
int main() {
int x, y, k;
while (cin >> x >> y >> k) {
cout << root(x, y, k) << endl;
}
return 0;
}