求root(N,k)

题目描述

https://www.nowcoder.com/practice/9324a1458c564c4b9c4bfc3867a2aa66?tpId=40&tqId=21347&rp=1&ru=/ta/kaoyan&qru=/ta/kaoyan/question-ranking

    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; 
} 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值