leetcode 372 超级次方

你的任务是计算 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
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

这道题涉及到许多数学算法,算是给我上了一课吧,算法不仅仅是动态规划,贪心,回溯等.还包括许多经典的数学定理,而这些数学定理也可以翻译成编程语言.如果要完成这道题,需要具备一些数学知识,那么我们就从这些数学知识开始吧!在那之前我先把答案写出来结合答案来理解会更好理解(我其实也没做出来,是看着答案一步步理解整个做题思路的.)

    public static int superPow(int a ,int[] b){
        int c = 1337;
        int exp = 0;
        int phi = euler(c);
        for(int i=0;i<b.length;i++){
        	exp = (exp*10+b[i])%phi;
        }
        return qucikPow(a,exp,1337);
    }
    //快速幂计算
    public static int qucikPow(int a,int b,int c){
        int ans =1;
        a %= c;
        while(b>0){
            if((b&1)==1){
                ans = (ans*a)%c;
            }
            b >>=1;
            a = (a*a)%c;
        }
        return ans;
    }
    //欧拉函数
    public static int euler(int n){
        int ret= n;
        for(int i=2;i*i<n;i++){
            if(n%i==0){//n的质因数
                ret = ret/n*(n-1); //欧拉函数公式
                while(n%i==0){//去掉质因数i
                    n/=i;
                }
            }
        }
        if(n>1){//n本来就是质数 f(n) = n-1;
            ret = ret/n*(n-1);
        }
        return ret;
    }

1.欧拉定理(欧拉费马定理)

数论中,欧拉定理,(也称费马-欧拉定理)是一个关于同余的性质。欧拉定理表明,若n,a为正整数,且n,a互质,则:

证明我就不证明了,可以参考百度百科:欧拉定理

怎么理解这个公式?如果n和a为正整数,且n,a互质,则a的n的欧拉函数次方与1对模n同余.(欧拉定理的同余性质).φ(n)在数论中表示n的欧拉函数.那么什么是欧拉函数呢?

2.欧拉函数

数论,对正整数n,欧拉函数是小于或等于n的正整数中与n互质的数的数目(因此φ(1)=1).

证明我也不证明了,可以参考百度百科:欧拉函数

怎么理解这个公式?对于任意正整数n,都有小于或等于n且互质的正整数数目为: φ(n)=n*(1-1/p1)*(1-1/p2)*(1-1/p3)*(1-1/p4)…..(1-1/pn),其中p1,p2,p3........pn为n的质因数.(什么是质因数?质因数素因数质因子)在数论里是指能整除给定正整数质数。除了1以外,两个没有其他共同质因子的正整数称为互质。因为1没有质因子,1与任何正整数(包括1本身)都是互质。正整数的因数分解可将正整数表示为一连串的质因子相乘,质因子如重复可以用指数表示。根据算术基本定理,任何正整数皆有独一无二的质因子分解式 [1]  。只有一个质因子的正整数为质数。)

翻译成java代码:

 //欧拉函数
    public static int euler(int n){
        int ret= n;
        for(int i=2;i*i<n;i++){
            if(n%i==0){//n的质因数
                ret = ret/n*(n-1); //欧拉函数公式
                while(n%i==0){//去掉质因数i
                    n/=i;
                }
            }
        }
        if(n>1){//n本来就是质数 f(n) = n-1;
            ret = ret/n*(n-1);
        }
        return ret;
    }

3.快速幂计算

可以参考这篇文章

4.最后

我们已经掌握了解决这道题的所有数学知识,那么应该怎么使用这些数学知识来解题呢?结合前面的答案请看:

    public static int superPow(int a ,int[] b){
        int c = 1337;
        int exp = 0;
        //计算欧拉函数,后面我们要使用
        int phi = euler(c);

        /**
        
            根据欧拉定理降幂
            在本题中phi = 1140;
            带入欧拉定理可得: a^1140 ≡ 1 (mod 1337);
            需要我们计算的式子为: a^f(n)%1337;      //f(n)表示整个指数表达式
            那么根据上面欧拉定理同余性质我们可以求得:
                a^f(n) % 1337 = ((a^1140)^(f(n)/1140) * a^(f(n)%1140))%1337
                              = (1^(f(n)/1140) * a^(f(n)%1140))%1337
                              = a^(f(n)%1140) %1337
            现在已经到达了降幂的目的,先前指数为f(n)而现在的指数为f(n)%1140;
            for循环做的事情就是求f(n)%1140;
            举个栗子在本题中f(n)表示数组[4,5,7,5,8]表示的值,即45758%1140,但是题目中没有说明这个数组的范围到底有多大,如果超出int范围值就会报错.所以我们用for循环来模拟常规的求余运算(PS:我也是看了很久才看懂这个for循环在干嘛!)
            常规求余运算:
            被除数    4,除数1140,商0余0,
            被除数   45,除数1140,商0余0,
            被除数  457,除数1140,商0余0,
            被除数 4575,除数1140,商4余15,
            被除数  158,除数1140,商0余158.(高位的余数*10借给低位)
        */
        for(int i=0;i<b.length;i++){
        	exp = (exp*10+b[i])%phi;//(高位的余数*10借给低位)
        }
        //此时的幂经过降幂之后一定小于phi(本题为1140)
        return qucikPow(a,exp,1337);
    }
    //快速幂计算
    public static int qucikPow(int a,int b,int c){//a底数,b指数,c模
        int ans =1;
        a %= c;
        while(b>0){
            if((b&1)==1){
                ans = (ans*a)%c;
            }
            b >>=1;
            a = (a*a)%c;
        }
        return ans;
    }
    //欧拉函数
    public static int euler(int n){
        int ret= n;
        for(int i=2;i*i<n;i++){
            if(n%i==0){//n的质因数
                ret = ret/n*(n-1); //欧拉函数公式
                while(n%i==0){//去掉质因数i
                    n/=i;
                }
            }
        }
        if(n>1){//n本来就是质数 f(n) = n-1;
            ret = ret/n*(n-1);
        }
        return ret;
    }

5.补充

补充一个例子,因为可能对欧拉定理降幂可能理解不到.我们举一个实际的例子 计算9^243的个位数.实际上是9^243对模10求余.9和10互质(公因子只有1).根据欧拉函数φ(10) = 4,则有 9^4 ≡ 1(mod 10).所以 9^243 = (9^4)^60*9^3≡1^60*9^3≡27≡7(mode 10),所以9^243个位数是7.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值