快速幂——求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

解答思路:(来自牛客网coder:二十三”)

通过数学公式推导: Nr = N%(k-1)
由此得到最终的结果值为N%(k-1),当值为0时由于值域限制>0,结果就为k-1。
问题就转为求
N%(k-1)【本题的关键】
这题考到了快速幂取模
首先第一个问题幂积的值(N)太大,无法保存下来,所以要分部取模。
这里的原理是积的模等于模的积。
要想分部就要将求幂的过程分部,这就用到了二分求幂:
int power(int a,int b)
{
    int ans=1;
    while(b!=0)
    {
        if(b%2==1)
           ans*=a;
        b/=2;
        a*=a;
    }
    return ans;
}

以上代码是求a的b次幂,原理是将b化为它的二进制形式,每位二进制对应不同的a的权重
例如:
0      1    0   0
a^8 a^4 a^2 a求a^4。
代码里b/=2是对二进制数进行右移,同时a*=a增大权值,当该位为1时(b%2==1)将相应的权值乘在ans上。这样就可以求出相应的幂值。
再根据 乘积取模和取模后再乘积结果不变 的原理,将取模加入到二分求幂的过程中:
ans = 1;
while(y!=0)
{
    if(y%2==1)
    ans = x*ans%k;//此处进行取模
    y/=2;
    x = x*x%k;//此处进行取模(只要是乘积的过程中的值,都可以加上取模)
}
return ans;
这样既加快了速度,由避免了数值太大溢出的问题。
不要忘记最后结果判断是否为0,为0时修改为k-1

代码:

#include<iostream>
#include<cstdio>
using namespace std;
long long root(long long x,long long y,int k)
{
    long long ans = 1;
    while(y!=0)
    {
        if(y%2==1)
          ans = x*ans%k;
        y/=2;
        x = x*x%k;
    }
        return ans;
}
int main()
{
    int x,y,k;
    cin>>x>>y>>k;
    int ans = root(x,y,k-1);
    if(ans == 0)
        ans = k-1;
    cout<<ans<<endl;
    return 0;
}

 

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值