P1495 【模板】中国剩余定理(CRT)/ 曹冲养猪 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
题目描述
自从曹冲搞定了大象以后,曹操就开始捉摸让儿子干些事业,于是派他到中原养猪场养猪,可是曹冲满不高兴,于是在工作中马马虎虎,有一次曹操想知道母猪的数量,于是曹冲想狠狠耍曹操一把。举个例子,假如有 头母猪,如果建了 个猪圈,剩下 头猪就没有地方安家了。如果建造了 个猪圈,但是仍然有 头猪没有地方去,然后如果建造了 个猪圈,还有 头没有地方去。你作为曹总的私人秘书理所当然要将准确的猪数报给曹总,你该怎么办?
输入格式
第一行包含一个整数 —— 建立猪圈的次数,接下来 行,每行两个整数 ,表示建立了 个猪圈,有 头猪没有去处。你可以假定 互质。
输出格式
输出包含一个正整数,即为曹冲至少养母猪的数目。
样例 #1
样例输入 #1
3
3 1
5 1
7 2
样例输出 #1
16
提示
,,
思路
设原猪总数为 , 当前分了 个猪圈, 还剩下 个牛, 可以把几个条件用同余方程组描述:
而题目中又说 之间是两两互质, 因此可以使用 中国剩余定理(CRT) 来直接解决。
定义 , 为 的逆元, 即 满足 。 而对应的存在一个解 , 仅当 互质时成立, 此式子为构造得出, 直接记忆就行。
此解也非最小正整数解, 有可能为负数, 需要进行取模 。
另外求逆元还有基于费马小定理的快速幂求法, 但要求 与 互质, 这里不一定成立, 故还是用扩展欧几里得定理求出最小的 t。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 20;
LL a[N], b[N];
LL qmi(LL a, LL b, LL p)
{
LL res = 1;
while (b)
{
if (b & 1)
res = (res * a) % p;
a = (a * a) % p;
b >>= 1;
}
return res;
}
void exgcd(LL a, LL b, LL &x, LL &y)
{
if (!b)
{
x = 1, y = 0;
return;
}
exgcd(b, a % b, y, x);
y -= (a / b) * x;
return;
}
void solve()
{
LL n;
cin >> n;
LL M = 1;
for (int i = 0; i < n; i++)
{
cin >> b[i] >> a[i];
M *= b[i];
}
LL res = 0;
for (int i = 0; i < n; i++)
{
LL mi = M / b[i];
LL t, x;
exgcd(mi, b[i], t, x);
res = (res + (a[i] * t * mi % M)) % M;
}
cout << (res % M + M) % M << endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
solve();
return 0;
}