代码:
定一个res存储结果
C++每秒执行107—— 108,如果直接用循环会超时,
aaaa… 若个数是奇数等同于 a * (a a a…)
aaaa… 若个数是偶数等同于 a*a * (a *a *a…)
相乘的个数为奇数的时候 直接将存储的结果res * a
相乘的个数为偶数的时候 将a = a * a
按照朴素算法就是把a连乘b次,这样一来时间复杂度是O(b)也即是O(n)级别,快速幂能做到O(logn)。
abab,那么其实b是可以拆成二进制的,该二进制数第i位的权为2(i−1)2(i−1),例如当b==11时,a11=a(20+21+23)a11=a(20+21+23) 。
11的二进制是1011,11 = 2³×1 + 2²×0 + 2¹×1 + 2º×1,因此,我们将a¹¹转化为算 $a^(2^0)a^(2^1)a^(2^3) $ 。
由于是二进制,很自然地想到用位运算这个强大的工具: & 和 >> ,&运算通常用于二进制取位操作,例如一个数 & 1 的结果就是取二进制的最末位。还可以判断奇偶x&1==0为偶,x&1==1为奇。>>运算比较单纯,二进制去掉最后一位 。
#include<iostream> using namespace std; int main() { int a, b, p; cin >> a >> b >> p; int res = 1 % p; /*思路实际上是每次去用个位去模,然后乘上高位再继续模*/ while (b) { if (b & 1)//个位是1 a&1 代表的意思是a和1做二进制的且运算 即看a的最后边那一位是不是1 是1的话 返回1 否则返回0 { cout <<"(b & 1)"<< (b & 1) << endl; res = res * 1ll * a % p;//强制转换为long long 形式 cout << "res"<<res << endl; } a = a * 1ll * a%p; //十位 cout <<"a= "<< a << endl; b >>= 1;//个位去掉 } cout << res << endl; return 0; }