LeetCode50/372 Pow(x,n)/超级次方

原题目
题目一:pow(x,n):

实现 pow(x, n) ,即计算 x 的 n 次幂函数。
示例 1:
输入: 2.00000, 10
输出: 1024.00000
示例 2:
输入: 2.10000, 3
输出: 9.26100
示例 3:
输入: 2.00000, -2
输出: 0.25000
解释: 2-2 = 1/22 = 1/4 = 0.25
说明:
-100.0 < x < 100.0
n 是 32 位有符号整数,其数值范围是 [−231, 231 − 1] 。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/powx-n

题目二:超级次方

你的任务是计算 ab 对 1337 取模,a 是一个正整数,b 是一个非常大的正整数且会以数组形式给出。
示例 1:
输入: a = 2, b = [3]
输出: 8
示例 2:
输入: a = 2, b = [1,0]
输出: 1024

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/super-pow

题目分析
第一题:

方法一:直接法:每次都乘一次x,直到第n次结束,但这样效率不高,时间复杂度为O(n),所以优化了一下,x为1或-1.或值非常小的时候的情况,另外考虑。

方法二:使用位运算优化:将每次的次幂以1 2 4 8的形式减小,即看成二进制,每次向右移一位,让乘数每次平方,判断n的每位上的二进制是否为1,为一就将返回值乘以乘数,直到n为0为止。时间复杂度O(log2n)。

第二题:

方法一:我们发现,次方数很大且每一位存放在一个数组中,所以我们可以考虑每一位所乘之数,例如次方为个位时,乘数为a,每次乘一个a就行了,次方为十位时,每次加十乘数为a的十次方,以此类推,将每此的乘积乘起来
方法二,我们发现,任何数的次方的取余余数会形成一个循环,我们将这个循环里的数存入数组中,用次方数对循环的大小取余对应数组的数就是解

完整代码

第一题

double myPow(double x, int n){
    long long int n1=fabs(n);//将n传给n1,应为n的负数部分比正数多一个,所以取绝对值后要用长整形
    double res=1.0,x1;//res为最后的结果,x1为x的对应值
    if(x==1||x==-1&&n%2==0)return 1;//1的任何次幂都为1,-1的次方为偶数时为1
    if(x==-1&&n%2==1)return -1;//-1的次方为奇数时为-1
    x1=n<0?(1/x):x;//如果次方小于0,那x的值就是x的倒数
    while(n1&&res)//直到n1为0或res为0,n1为0说明乘完所有数,res为0说明res非常小,近似为0
    {
        res*=x1;
        n1--;
    }
    return res;
}
double myPow(double x, int n){
    long N = n;
    if(n < 0) {
        x = 1/x;
        N = -N;
    }
    double base = x;
    double result = 1.0;
    while(N) {
        if(N & 1)
            result *= base;
        base *= base;
        N >>= 1;
    }
    return result;
}

第二题

int superPow(int a, int* b, int bSize){
    int a1=a%1337,a2=a1;
    int res=1;
    for(int i=bSize-1;i>=0;i--)
    {
        for(int j=0;j<b[i];j++)
        {
            res=(res*a1)%1337;
        }
        for(int j=0;j<9&&i!=0;j++)
        {
            a1=(a1*a2)%1337;
        }
        a2=a1;
    }
    return res;
}
/*
观察2^n % 10,发现当n增加时,余数构成2、4、8、6、2的循环,循环大小为4
所以2^n%10 =2^(n%4)%10
所以a^b%1337 = (a%1337)^(b%循环大小)%1337。
用数组m储存余数循环,则mSize就是循环大小,计算b%mSize,查表m可以得到答案。
第二个循环计算b%mSize
*/

int superPow(int a, int* b, int bSize)
{
    if(a == 1)
        return 1;
    int m[1339], mSize, x;
    mSize = 0;
    m[1] = 0;
    m[0] = 1;
    a = a % 1337;
    x = a;
    while(x != m[1])
    {
        m[++mSize] = x;
        x = x * a % 1337;
    }
    x = 0;
    for(int i = 0; i < bSize; i++)
    {
        x = (10 * x + b[i]) % mSize;
    }
    return m[x];
}
总结

掌握数学思维

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Baal Austin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值