快速幂

资料来源

以 $n^m$ 举例

由于指数 m 总能用二进制表示,而幂次上的加法就是多个指数幂次相乘

也就是说,当 $m = k_1+k_2+...+k_t$ 时($k_i$表示 m 在二进制下第 i 位是 1 ),

每个 $n^m$ 都可以拆成 $n^{k_1+k_2+...+k_t} = n^{k_1} * n^{k_2} * ... * n^{k_t}$

所以我们就只需要求这里的 $k_1$,$k_2$,...,$k_t$

而求法就是 $m$ & $1$

需要注意的一点是:

  aa 需要每次都平方,因为若现在次数为$n^8$,那么下一次就应该是$n^16$了,

  这个转换是平方关系,所以每次都需要平方一下

上代码:

#include<iostream>
#include<cstdio>
#define ll long long
using namespace std;
ll n,m;
ll big( ll a,ll b ){
    ll ans = 1,aa = a;
    while( b ){
        if( b & 1 ){ //二进制下为 1,应当乘上该位 
            ans *= aa;//乘上该位 
            printf( "ans = %ld  ",ans );
        }
        aa *= aa;//相当于 a^2,如现在取到了8次,那下一次就应当选16次 
        printf( "a = %ld  ",a ); 
        b >>= 1;
        printf( "b = %ld\n",b );
    }
    return ans;
}
int main(){
    cin >> n >> m;
    cout << big( n,m ); 
    return 0;
} 
快速幂普通板子

 

需要模 p 的话,则为:

#include<iostream>
#include<cstdio>
#define ull unsigned long long
using namespace std;

ull n,m,k;

int main(){
    cin >> n >> m >> k;//底数,指数,模数 
    
    ull aa = n,ans = 1,p = n;
    while( m > 0 ){
        if( m & 1 ){ //这一位上有 
            ans = ans * aa;
            ans %= k;
            printf( "ans = %lu\n",ans );
        }
        aa *= aa;
        aa %= k;
        m >>= 1;
        printf( "b = %ul\n",m );
    }
    
    cout << ans%k;
    
    return 0;
}
快速幂+模运算

 

posted @ 2021-10-22 16:21  little_sheep_xiaoen  阅读(17)  评论(0编辑  收藏  举报