位運算_CH0102_64位整數乘法
阿新 • • 發佈:2018-12-16
思路分析:給出兩種方法, 法1基於遞推, 法2利用C++基本資料型別的性質
法1:
考慮b的二進位制表示, (a * b) mod p = (a * ()) mod p = () mod p
又: , 則可先求出s = , 且s < p <= , 可直接使用語句: s * 2 % p 計算
至此,首先計算, 然後遞推即可, AC程式碼如下:
//CH0102_64位整數乘法 #include <iostream> #include <cstdio> using namespace std; //返回(a * b) mod p的值, 要求:1 <= a, b, p <= 10^18 long long getVal(long long a, long long b, long long p){ long long ans = 0, tmp = a % p; for(; b; b >>= 1, tmp = tmp * 2 % p) if(b & 1) ans = (ans + tmp) % p; return ans; } int main(){ long long a, b, p; scanf("%lld %lld %lld", &a, &b, &p); cout << getVal(a, b, p) << endl; return 0; }
法2:
由 (a * b) mod p = a * b - , 且該等式兩端的值小於, 可先計算的值, 如何計算s? 考慮到s <= , 利用C++中long double的有效數字為18~19位, 因此對a, b, p使用long double計算a * b / p的值, 對結果取整數部分即為s的值.繼而將a, b, s, p均定義為unsigned long long 型別, 依據C++中unsigned long long運算性質, 表示式a * b - s * p的值為其數學上的實際值對取模, 因為其實際值小於, 故表示式a * b - s * p 為其實際值, 具體步驟如下AC程式碼所示:
//CH0102_64位整數乘法 #include <iostream> #include <cstdio> using namespace std; typedef unsigned long long ull; //返回(a * b) mod p的值, 要求:1 <= a, b, p <= 10^18 ull getVal(ull a, ull b, ull p){ return a * b - (ull)((long double)a * b / p) * p; } int main(){ long long a, b, p; scanf("%lld %lld %lld", &a, &b, &p); cout << getVal(a, b, p); return 0; }