求root(n,k)

题目描述

    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 <cstdio>
#include <iostream>
using namespace std;
int f(int x,int y,int k)
{
  if(y==1)
  {
    if(x<k)
    return x;
    while(x>=k)
    {
      int ans=0;
      while(x)
      {
        ans+=x%k;
        x=x/k;
      }
      x=ans;
    }
    return x;
  }
  else
  {
    if(y%2==0)
      return f(f(x,y/2,k)*f(x,y/2,k),1,k);
    else return f(f(x,y/2,k)*f(x,y/2,k)*f(x,1,k),1,k);
  }
}
int main()
{
  int answer;
  int x,y,k;
  while(cin>>x>>y>>k)
  {
    answer=f(x,y,k);
    cout<<answer<<endl;
  }
  return 0;
}

posted @ 2019-11-25 20:05  青豆666  阅读(313)  评论(0)    收藏  举报