64位整数乘法 高精度

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

跟快速幂的实质一样

我们用快速幂的思想,将b用二进制表示

b=ck-12k-1+ck-22k-2+…+c020

  那么:

 a×b=a×(ck-12k-1+ck-22k-2+…+c020)=a×ck-1×2k-1+a×ck-2×2k-2+…+a×c0×20

  又

a×2i=(a×2i-1)×2

  于是我们可以递推地计算出a×2i并且每次计算把答案加入ans中与快速幂不同的是ans的初始化并不是赋值为1而是清0.时间复杂度为O(log2 b).

  在此基础上我们考虑如果a,b是负数那怎么办呢?为了解决这个问题我们考虑打一个标记w,我们将w的初始值赋值为1,如果a,b的值是负数的话就把w值取w=-w(a,b均做一次判断),我们把返回ans×w即可.

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include <climits>
#include<queue>
#include<vector>
#include <string.h>
#include <math.h>
#include<map>
#include<string.h>
#define ll long long
using namespace std;
ll mul(ll a,ll b,ll p){
    ll ans=0;
    int w=1;
    if(b<0){
        w=-w;
        b=-b;
    }
    if(a<0){
        w=-w;
        a=-a;
    }
    if(a<b){
        ll t=a;
        a=b;
        b=t;
    }
    while(b){
        if(b&1){
            ans=(ans+a)%p;
        }
        a=(a*2)%p;
        b>>=1;
    }
    return w*ans;
}
int main()
{
    //    freopen("in.txt","r",stdin);
    ll p,a,b;
    scanf("%lld %lld %lld",&a,&b,&p);
    printf("%lld\n",mul(a,b,p));
    return 0;

}

这只是一个简化一定程度的算法,具体可查看

https://www.cnblogs.com/FJ-LinHua/p/9152631.html

猜你喜欢

转载自blog.csdn.net/weixin_41370251/article/details/80807854