【模板】有理数取余
https://www.luogu.com.cn/problem/P2613
题目描述
给出一个有理数 c=abc=\frac{a}{b}c=ba,求 c mod 19260817c \bmod 19260817cmod19260817 的值。
这个值被定义为 bx≡a(mod19260817)bx\equiv a\pmod{19260817}bx≡a(mod19260817) 的解。
输入格式
一共两行。
第一行,一个整数 aaa。
第二行,一个整数 bbb。
输出格式
一个整数,代表求余后的结果。如果无解,输出 Angry!。
样例 #1
样例输入 #1
233
666
样例输出 #1
18595654
提示
对于所有数据,保证 0≤a≤10100010\leq a \leq 10^{10001}0≤a≤1010001,1≤b≤10100011 \leq b \leq 10^{10001}1≤b≤1010001,且 a,ba, ba,b 不同时是 192608171926081719260817 的倍数。
代码
扩展欧几里得算法
#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
using ll = long long;
constexpr ll P = 19260817; // 使用constexpr表示为常量
// 扩展欧几里得算法
ll exgcd(ll a, ll b, ll &x, ll &y) {
// 递归终止
if (b == 0) {
x = 1;
y = 0;
return a;
}
// 递归计算
ll x1, y1, gcd;
gcd = exgcd(b, a % b, x1, y1);
x = y1;
y = x1 - a / b * y1;
return gcd;
}
// 求乘法逆元
ll mod_inverse(ll a) {
ll x, y;
ll gcd = exgcd(a, P, x, y);
if (gcd != 1) {
return -1;
} else {
return (x % P + P) % P;
}
}
void solve() {
// a和b太长,所以通过字符串输入
string a_str, b_str;
cin >> a_str >> b_str;
ll a = 0, b = 0;
for (char c : a_str) {
a = (a * 10 + (c - '0')) % P;
}
for (char c : b_str) {
b = (b * 10 + (c - '0')) % P;
}
ll b_inv = mod_inverse(b);
if (b_inv == -1) {
cout << "Angry!" << endl;
} else
cout << (a * b_inv) % P << endl;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
solve();
return 0;
}
费马小定理
#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
using ll = long long;
constexpr ll P = 19260817;
ll fast_pow(ll a, ll b) {
ll res = 1;
a %= P;
while (b) {
if (b & 1) {
res = (res * a) % P;
}
a = (a * a) % P;
b >>= 1;
}
return res;
}
void solve() {
string a_str, b_str;
cin >> a_str >> b_str;
ll a = 0, b = 0;
for (char c : a_str) {
a = (a * 10 + (c - '0')) % P;
}
for (char c : b_str) {
b = (b * 10 + (c - '0')) % P;
}
cout << (a * fast_pow(b, P - 2)) % P << endl;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
solve();
return 0;
}
-
使用
constexpr而不是const表示常量,constexpr确保常量在编译时就可以计算,这对性能有很大的提升,因为它消除了运行时的计算。 -
使用字符串输入较长的数字,可以在转换的过程中就进行取模操作,而得数字的大小始终在指定范围内
// a和b太长,所以通过字符串输入 string a_str, b_str; cin >> a_str >> b_str; ll a = 0, b = 0; for (char c : a_str) { a = (a * 10 + (c - '0')) % P; } for (char c : b_str) { b = (b * 10 + (c - '0')) % P; }
360

被折叠的 条评论
为什么被折叠?



