快速幂算法(C/C++)

传统解法

我们知道求一个数的幂可以表示为(ab)意思是a的b次方。如28运算结果是256运用for循环8次完全可以得到正确结果,但当b的值为10000,1000000时我们要得到幂函数的结果就相当麻烦了,那么是否有一种简单的方法可以使我们迅速得到幂函数的结果呢? 这就是今天我们要介绍的快速幂算法!

快速幂简介

如28可以等价于((((22)2)2)2),这时只需进行四次运算就可以得到本需要八次运算才可以得到的结果,在b数值较小的情况下我们不能较为直接的感觉到快速幂算法的优异性,但当b为10000甚至更大时速度会大大提高,减少时间复杂度一半。如当b=100000时,运用快速幂算法,直接减少了50000次运算,效率大大提高。

代码实现

当b为偶数时,它可以被分成一个个相同的(2)次模块。但当b为奇数时,b-1为偶数,算出结果后再乘以自身就可以得到运算结果。

long long fastPower(long long base, long long power) {
    long long result = 1;
    while (power > 0) 
    {
        if (power % 2 == 0)//如果指数为偶数
         {
            power = power / 2;    //把指数缩小为一半
            base = base * base ;//底数变大成原来的平方
          } 
     else //如果指数为奇数
          {
            power = power - 1;//把指数减去1,使其变成一个偶数
            result = result * base ;//此时记得要把指数为奇数时分离出来的底数的一次方收集好
            power = power / 2;//此时指数为偶数,可以继续执行操作
            base = base * base ;
           }
    }
    return result;
} 

拓展

现在我们来看这个例题点击此处
此题要求 ,求ab的后三位。当b的值充分大时,因为指数增长的缘故,即使long long也不能存下所有的结果。
所可以根据以下“取模”运算法则对代码进行优化

 1.  (a + b) % p = (a % p + b % p) % p (1)
 2.  (a - b) % p = (a % p - b % p ) % p (2)
 3.  (a * b) % p = (a % p * b % p) % p  (3)

优化后

long long fastPower(long long base, long long power) {
    long long result = 1;
    while (power > 0) {
        if (power % 2 == 0) {
            //如果指数为偶数
            power = power / 2;//把指数缩小为一半
            base = base * base % 1000;//底数变大成原来的平方
        } else {
            //如果指数为奇数
            power = power - 1;//把指数减去1,使其变成一个偶数
            result = result * base % 1000;//此时记得要把指数为奇数时分离出来的底数的一次方收集好
            power = power / 2;//此时指数为偶数,可以继续执行操作
            base = base * base % 1000;
        }
    }
    return result;
 }

终极优化

借鉴一位大佬

原文链接: https://blog.csdn.net/qq_19782019/article/details/85621386

正文

在C语言中,power%2==1可以用更快的“位运算”来代替,例如:power&1。因为如果power为偶数,则其二进制表示的最后一位一定是0;如果power是奇数,则其二进制表示的最后一位一定是1。将他们分别与1的二进制做“与”运算,得到的就是power二进制最后一位的数字了,是0则为偶数,是1则为奇数。例如5是奇数,则5&1=1;而6是偶数,则6&1=0;因此奇偶数的判断就可以用“位运算”来替换了。

移动前

同样,对于power=power/2来说,也可以用更快的“位运算”进行替代,我们只要把power的二进制表示向右移动1位就能变成原来的一半了。

移动后

最终结果
long long fastPower(long long base, long long power) {
    long long result= 1;
    while (power > 0) {
        if (power & 1) {//此处等价于if(power%2==1)
            result = result * base % 1000;
        }
        power >>= 1;//此处等价于power=power/2
        base = (base * base) % 1000;
    }
    return result;
}

通过实验可得最终运算速度接近于零,可以看出快速幂算法是一种高效成熟的算法。

第一次写博客,完全懵 B;

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
这里提供一个简单的RSA算法的C/C++实现。 算法流程: 1.选择两个大质数p和q,计算n=p*q。 2.计算欧拉函数φ(n)=(p-1)*(q-1)。 3.选择一个整数e,1< e <φ(n),且e与φ(n)互质。 4.计算d,使得d*e≡1(mod φ(n))。 5.公钥为(n,e),私钥为(n,d)。 6.加密:C=M^e(mod n)。 7.解密:M=C^d(mod n)。 代码实现: ```c++ #include <iostream> #include <cstring> #include <cmath> using namespace std; //计算最大公约数 int gcd(int a, int b) { if (b == 0) return a; return gcd(b, a % b); } //判断是否为质数 bool isPrime(int n) { if(n <= 1) return false; for(int i=2; i<=sqrt(n); i++) { if(n%i == 0) return false; } return true; } //生成大质数 int generatePrime(int min, int max) { int prime; do { prime = rand() % (max - min + 1) + min; }while(!isPrime(prime)); return prime; } //计算模 int modPower(int a, int b, int m) { int res = 1; while(b > 0) { if(b & 1) res = (res * a) % m; a = (a * a) % m; b >>= 1; } return res; } //生成公私钥对 void generateKey(int &n, int &e, int &d) { int p, q, phi_n; do { p = generatePrime(100, 1000); q = generatePrime(100, 1000); n = p * q; phi_n = (p - 1) * (q - 1); }while(gcd(phi_n, 65537) != 1); //65537为常用值 e = 65537; d = 0; while((d*e) % phi_n != 1) d++; } //加密 void encrypt(int n, int e, char *msg, int *cipher) { int len = strlen(msg); for(int i=0; i<len; i++) { cipher[i] = modPower(msg[i], e, n); } } //解密 void decrypt(int n, int d, int *cipher, char *msg) { int len = strlen(msg); for(int i=0; i<len; i++) { msg[i] = modPower(cipher[i], d, n); } } int main() { int n, e, d; generateKey(n, e, d); cout << "公钥:" << "(" << n << "," << e << ")" << endl; cout << "私钥:" << "(" << n << "," << d << ")" << endl; char msg[100]; cout << "请输入要加密的明文:"; cin.getline(msg, 100); int cipher[100]; encrypt(n, e, msg, cipher); cout << "密文:"; for(int i=0; i<strlen(msg); i++) { cout << cipher[i] << " "; } cout << endl; char dec[100]; decrypt(n, d, cipher, dec); cout << "解密后的明文:" << dec << endl; return 0; } ``` 这个实现中使用了随机生成质数的方法,生成的质数范围在100到1000之间。公钥中的e取65537,私钥中的d通过枚举计算得到。加密和解密过程中使用了模运算。整个程序可以编译运行,输入要加密的明文,即可得到加密后的密文和解密后的明文。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值