基本思想:
- 直接扔掉高位的数字,在能乘的范围内乘.
- 由于正常情况下有符号整数会出现溢出的情况,所以使用无符号数值(unsigned long long)即可.
具体实现:
- 已知 a%p=a-⌊a/p⌋*p(a减去尽可能多的p).
- 则a*b%p=a*b-⌊a*b/p⌋*p.
- 这里a*b不会变成负数,这是由于使用的是unsigned long long.
- 接下来,使用long double保存b/p,在强转成unsigned long long类型后再乘以a,最终乘以p即可得出被减数.
- 两数相减即可得出最终结果.
常见问题:
- 这样不会存在精度问题吗?
- 会,所以不能对太大的模数使用这个方法。
#include<cstdio> #include<iostream> #define ll long long #define ld long double #define ul unsigned long long using namespace std; ll mul(ll a,ll b,ll p){ ul first=(ul)a*b; ul second=((ll)((ld)a*b/p))*p; return (ll)(first-second); } int main(){ ll a,b,p; cin>>a>>b>>p; ll ans=mul(a,b,p); cout<<ans<<endl; return 0; }