64位整数乘法讲解-And-AcWing-90. 64位整数乘法-方法二-《算法竞赛进阶指南》

60 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

@TOC

64位整数乘法

题目描述

aba*bmodmod取模的值

1a,b,mod10181\leq a,b,mod\leq 10^{18}

问题分析

先不考虑__int128\_\_int128

利用ab%mod=abab/modmoda*b\%mod=a*b-\lfloor a*b/mod\rfloor*mod(其中\lfloor \rfloor表示向下取整)

aba*bxxab/mod\lfloor a*b/mod\rflooryy

问题有22个,一是如何计算出ab/mod\lfloor a*b/mod\rfloor,而是如何计算xymodx-y*mod

因为long doublelong\ double在十进制下的有效数字有1818~1919位,当a,b<moda,b<modcc也一定小于modmod。所以long doublelong\ double可以胜任,再把结果强制转换为unsigned long longunsigned\ long\ long即可。yy由此计算。

因为abcmoda*b-c*mod其实就是ab%modmod<264a*b\%mod\leq mod< 2^{64},所以abcmod=(abcmod)%264a*b-c*mod=(a*b-c*mod)\%2^{64},又因为unsigned long longunsigned\ long\ long溢出时相当于对2642^{64}自动取模,所以xymodx-y*mod由此计算。

时间复杂度为O(1)O(1)


64位整数乘法模板

typedef long long ll;
typedef unsigned long long ull;

ll mul(ll a, ll b, ll mod)
{
    a %= mod, b %= mod;
    ull c = (long double)a * b / mod;
    ull x = a * b, y = c * mod;
    ll ans = (ll)x % mod - (ll)y % mod;
    if (ans < 0)
        ans += mod;
    return ans;
}

AcWing-90. 64位整数乘法

传送门

Problem Description

aba*bmodmod取模的值

Tips

1a,b,mod10181\leq a,b,mod\leq 10^{18}


AC代码


#include <bits/stdc++.h>
using namespace std;
#define mem(a) memset(a, 0, sizeof(a))
#define dbg(x) cout << #x << " = " << x << endl
#define fi(i, l, r) for (int i = l; i < r; i++)
#define cd(a) scanf("%d", &a)

typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a, ll b, ll mod)
{
    a %= mod, b %= mod;
    ull c = (long double)a * b / mod;
    ull x = a * b, y = c * mod;
    ll ans = (ll)x % mod - (ll)y % mod;
    if (ans < 0)
        ans += mod;
    return ans;
}

int main()
{
    ll a, b, c;
    cin >> a >> b >> c;
    cout << mul(a, b, c) << endl;
    return 0;
}

同步发文于我的CSDN,原创不易,转载请附上原文链接哦~
Tisfy:letmefly.blog.csdn.net/article/det…