leetcode 372.超级次方

原题

372.超级次方
在这里插入图片描述
——————————————————————————————————————
我做的第一道中等难度的题

题解

方法一

指数二分降幂。
本思路java代码示例:

/*
 *@v7fgg
 *执行用时:10 ms, 在所有 Java 提交中击败了53.28%的用户
 *内存消耗:39.9 MB, 在所有 Java 提交中击败了100.00%的用户
 *2020年6月24日 12:08
 */
class Solution {
    public int superPow(int a, int[] b) {
        int ans=1;
        a%=1337;
        for(int i=0;i<b.length;i++){
            ans=cifang(ans,10)*cifang(a,b[i])%1337;
        }
        return ans;
    }
    public int cifang(int a,int p){
        //计算a的p次方模1337的值,p不大于10
        if(p==0){return 1;}
        if(p==1){return a;}
        return cifang(a,p/2)*cifang(a,p-p/2)%1337;
    }
}

方法二 利用欧拉函数以及大数降幂取模

(也是看过了并参考别人的思路后):

1、首先借助[欧拉函数]

(https://baike.baidu.com/item/%E6%AC%A7%E6%8B%89%E5%87%BD%E6%95%B0/1944850?fr=aladdin),算出作为模的底的1337有多少个小于它与之互质的正整数,即求出φ(1337)=1140,这个数的计算方法在其他人解答中多体现乘代码形式,而后带入1337再求出,我这里是走了一个小小的捷径,直接求出为1140;

2、就是下图的公式了

这里把原本以数组形式表示的超大的指数B,代码中用numB逐位取模的方法来大大减小其值,最后循环了新numB次求出题解
同余降幂
本思路代码示例:
java:

class Solution {
    public int superPow(int a, int[] b) {
          int numB=b[0];
          a=a%1337;
          if(a==0){
              return 0;
          }
          for(int i=1;i<b.length;i++){
              numB=(numB*10+b[i])%1140;
              //numB*=10;
          }
              numB+=1140;
              int x=a;
              for(int j=0;j<numB;j++){
                  x=x%1337;
                  x*=a;
              }x/=a;
              return x;
    }
}

java运行后时空利用:
在这里插入图片描述
python:

class Solution:
    def superPow(self, a: int, b: List[int]) -> int:
        a=a%1337
        bs=b[0]
        x=a
        if(a==0):
            return 0
        for i in range(1, len(b)):
            bs=(bs*10+b[i])%1140
        bs+=1140
        for j in range(0,bs):
            x=(x%1337)*a
        return int(x/a)    

c++

class Solution {
public:
    int superPow(int a, vector<int>& b) {
          int numB=b[0];
          a=a%1337;
          if(a==0){
              return 0;
          }
          for(int i=1;i<b.size();i++){
              numB=(numB*10+b[i])%1140;
          }
              numB+=1140;
              int x=a;
              for(int j=0;j<numB;j++){
                  x=x%1337;
                  x*=a;
              }x/=a;
              return x;
    }
};

另外强调一点错误的想法,本题中讲的是超级大的指数,而一般的long类型里面最大的也只有64位,倘若b数组给出长度成千上万,就远远不是计算机所能处理的了,所以在处理指数的时候,不能妄想把b数组一逐位乘10再加下一位的方法来得到这个指数,那是不可能的,因此才引进了降幂同余公式。一下是错误的java实例:

class Solution {
    public int superPow(int a, int[] b) {
          int numB=0;
          a=a%1337;
          if(a==0){
              return 0;
          }
          for(int i=0;i<b.length;i++){//b数组超长时在这里会报错越界
              numB+=b[i];
              numB*=10;
          }
              numB/=10;
              int x=a;
              for(int j=0;j<numB;j++){
                  x=x%1337;
                  x*=a;
              }x/=a;
              return x;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

可爱抱抱呀

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

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

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

打赏作者

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

抵扣说明:

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

余额充值