zoukankan      html  css  js  c++  java
  • 90. 64位整数乘法

    原题链接:64位整数乘法

    解题思路

    方法一

    类似快速幂的思想,把整数 b 用二进制表示,即b=c(k-1)pow(2,k-1)+c(k-2)pow(2,k-2)+......+c(0)pow(2,0),那么a*b=c(k-1)*a*pow(2,k-1)+c(k-2)*a*pow(2,k-2)+......+c(0)*a*pow(2,0)
    因为a*pow(2,i)=(a*pow(2,i-1))*2,若已求出a*pow(w,i-1) mod p,则计算(a*pow(2,i-1))*2 mod p时,运算过程中每一步的结果都不超过2*pow(10,18),仍然在64位整数 longlong 的表示范围内,所以很容易通过 k 次递推求出每个乘积项。当 c(i)=1 时,把乘积项累加到答案中即可。

    样例代码

    #include<bits/stdc++.h>
    using namespace std;
    unsigned long long mul(unsigned long long a,unsigned long long b,unsigned long long p)
    {
        a%=p,b%=p;
        unsigned long long c=(long double)a*b/p;
        unsigned long long x=a*b,y=c*p;
        long long ans=(long long)(x%p)-(long long)(y%p);
        if(ans<0)
            ans+=p;
        return ans;
    }
    int main()
    {
        long long a,b,p;
        cin>>a>>b>>p;
        cout<<mul(a,b,p);
        return 0;
    }
    

    方法二

    如果直接计算a乘b这会超过 long long 的最大范围,所以采用类似于快速幂的思想
    把 b写成二进制形式,然后如果某位上为1就加上它a*(2^n)次方(n与这位的位置有关)
    并且每次计算后取模就可以了

    例:计算 3*7
    
    7的二进制 111
    3*(2^0)=3
    3*(2^1)=6
    3*(2^2)=12
    

    观察可发现每次的可由前一次*2推出(记得取模)

    样例代码

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    int main()
    {
        ll a , b , p , res;
        cin >> a >> b >> p;
        res = 0;
        while (b)
        {
            if (b & 1)
                res = (res + a) % p;
            b >>= 1;
            a = 2 * a % p;
        }
        cout << res;
        return 0;
    }
    
  • 相关阅读:
    研究生第二学期总结
    Android应用开发EditText文本内容变化监听方法
    Android 自定义动画 Loading
    UML建模之活动图介绍(Activity Diagram)
    UML学习(二)-----类图
    UML系列图--用例图
    Lesson9 some interesting things in C#
    Lesson10 Fianl and fellings
    Lesson 7: C#多线程
    浅谈android Socket 通信及自建ServerSocket服务端常见问题
  • 原文地址:https://www.cnblogs.com/hnkjdx-ssf/p/14058494.html
Copyright © 2011-2022 走看看