题目地址


 基本思想:

  • 直接扔掉高位的数字,在能乘的范围内乘.
  • 由于正常情况下有符号整数会出现溢出的情况,所以使用无符号数值(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;
}