快速幂(取模)+大数乘法

理解快速幂:

假设我们要求a^b,那么其实b是可以拆成二进制的,该二进制数第i位的权为2^(i-1),例如当b==11时

  a^11=a(2^0+2^1+2^3)

11的二进制是1011,11 = 2³×1 + 2²×0 + 2¹×1 + 2º×1,因此,我们将a¹¹转化为算 a(2^0)*a(2^1)*a(2^3),也就是a^1*a^2*a^8

看出来快的多了吧原来算11次,现在算三次,但是这三项貌似不好求的样子....不急,下面会有详细解释。                                        由于是二进制,很自然地想到用位运算这个强大的工具:(位运算计算)

&和>>    

&运算通常用于二进制取位操作,例如一个数 & 1 的结果就是取二进制的最末位(因为1的二进制只有..0001,结合百科自行理解)。还可以判断奇偶x&1==0为偶,x&1==1为奇。

>>运算比较单纯,二进制去掉最后一位.

---------------------------------------------------------------------------------------------------------------------------------------

下面为自己对代码的理解,以 a^11=a(2^0+2^1+2^3)为例:

11的二进制是1011,11 = 2³×1 + 2²×0 + 2¹×1 + 2º×1

1.if(b%2)或if(b&1)    r*=base;来判断二进制末尾是否有权值(1则有,0则没有),有则乘上该位置上的权值

2.base*=base;    通过累乘得到下一个位置上的权值(由最后一位转为倒数第二位,2^0转为2^1,以此类推...) 注意每一步都要执行!

3.b/2或b>>=1;    二进制去掉最后一位.如1011变为101,再返回到第一步重新计算(需注意的是此时101的末尾的1其实2^1已由第二步base的累乘得出)

来看看代码吧:

1.快速幂

int power(int a,int b)
{
    int ans=1;
    while(b)
    {
        if(b%2) 
            ans*=a;

        a*=a;
        b/=2;
    }
    return ans;
}

/*int power(int a, int b) {
    int ans = 1;
    while (b) 
    {
        if (b&1)
            ans *= base;
         a*=a;
         b>>= 1;
    }
    return ans;
}*/
​

 

2.取模

主要源于(a*b)%c=(a%c*b%c)%c;

我的理解是a^b可以看成a*a*a*a....每合并一向便可以看成新的因子,所以同时要%c

#include
#include
#include
using namespace std;
long long x,y,c;
long long power(long long a,long long b)
{
    long long ans=1%c;
    a=a%c;
   // long long base=a;
    while(b)
    {
        if(b%2!=0)
            ans=(ans*a)%c;
        a=(a*a)%c;
        b/=2;
    }
    return ans;
}
int main()
{
    cin>>x>>y>>c;
    long long t=power(x,y);
    cout<

例题:

要求(A/B)%9973,但由于A很大,我们只给出n(n=A%9973)(我们给定的A必能被B整除,且gcd(B,9973) = 1)。

Input

数据的第一行是一个T,表示有T组数据。
每组数据有两个数n(0 <= n < 9973)和B(1 <= B <= 10^9)。

Output

对应每组数据输出(A/B)%9973。

Sample Input

2
1000 53
87 123456789

Sample Output

7922
6060

求b的逆元用到了快速幂取模,a/b=a*(b ^ (M-2)) (mod M) 

代码:

#include
#include
int power(int a,int b,int c)
{
    long long ans=1,base=a%c;
    while(b!=0)
    {
        if(b%2!=0)
            ans=(ans*base)%c;
        base=(base*base)%c;
        b/=2;
    }
    return ans;
}
int main()
{
    long long i,x,n,m,z;
    scanf("%lld",&x);
    for(i=0;i

3.大数乘法

题目:http://icpc.upc.edu.cn/problem.php?cid=1430&pid=1

题目描述

求 a 乘 b 对 p 取模的值,其中 1≤a,b,p≤10^18。

输入

第一行a,第二行b,第三行p。

输出

一个整数,表示a*b mod p的值。

样例输入

复制样例数据

2
3
9

样例输出

6

这个东西其实就是类似于快速幂(快速幂的一般写法通常称为反复平方法),这里只是将平方变为×2×2。相信理解快速幂的同学一定会明白这是什么意思吧!我直接贴个代码:

#include
#include
#include
#define ll long long
using namespace std;
const int maxn=1e5+10;
 ll a,b,p;
ll power(ll a,ll b)
{
    ll ans=0;
    while(b)
    {
        if(b&1)
            ans=(ans+a)%p;//注意变为+!
        a=(a*2)%p;//变为*2!
        b>>=1;
    }
    return ans;
}
int main()
{

    cin>>a>>b>>p;
    ll ans=power(a,b);
    cout<

大数乘法几种算法:https://blog.csdn.net/frankchenfu/article/details/82259794

你可能感兴趣的:(快速幂(取模)+大数乘法)