专栏文章
P1495 【模板】中国剩余定理(CRT)/ 曹冲养猪 题解
P1495题解参与者 2已保存评论 1
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @mipym3ia
- 此快照首次捕获于
- 2025/12/03 20:04 3 个月前
- 此快照最后确认于
- 2025/12/03 20:04 3 个月前
前置知识:同余、逆元、扩展欧几里得定理。
中国剩余定理用于求解如下形式的同余方程组:
其中, 两两互质。
求解的过程如下:
- 计算所有模数的积 。
- 依次考虑每一个方程。对于第 个方程:
- 计算 。
- 计算 在模 意义下的逆元 。
- 因为 两两互质,显然有 ,即逆元一定存在。
- 最终, 最小的非负整数解为 。
我们需要证明,以上算法所得到的 满足 。
根据以上 的定义,可以得到当 时,。
又根据逆元的定义,可以得到 。
因此:
即:。算法的正确性得证。
由于 不一定是质数,不能用费马小定理求逆元,所以用了扩展欧几里得定理来求。
C++:
本题运算过程中可能会爆
CPPlong long,需要使用 __int128 才能通过。#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 15;
int n, a[N], b[N];
pair<int, int> exgcd(int a, int b){
if(b == 0) return {1, 0};
auto [x, y] = exgcd(b, a % b);
return {y, x - a / b * y};
}
int inv(int a, int p){
auto [x, y] = exgcd(a, p);
return (x + p) % p; //exgcd 求出的解有可能是负的,所以取模一下转成正的
}
int CRT(int n, int *a, int *b){
int M = 1, x = 0;
for(int i=1; i<=n; i++) M *= a[i];
for(int i=1; i<=n; i++){
__int128 Mi = M / a[i], Ti = inv(Mi, a[i]);
x = (x + Mi * Ti * b[i] % M) % M;
}
return x;
}
signed main(){
cin.tie(nullptr) -> sync_with_stdio(false);
cin >> n;
for(int i=1; i<=n; i++) cin >> a[i] >> b[i];
cout << CRT(n, a, b);
return 0;
}
Python:
PYTHONdef exgcd(a, b):
if b == 0: return (1, 0)
x, y = exgcd(b, a % b)
return y, x - a // b * y
def inv(a, p): return exgcd(a, p)[0] % p
def CRT(n, a, b):
M = 1; x = 0
for i in range(n): M *= a[i]
for i in range(n):
Mi = M // a[i]; Ti = inv(Mi, a[i])
x += Mi * Ti * b[i]
return x % M
def main():
n = int(input())
a = [0] * n; b = [0] * n
for i in range(n):
a[i], b[i] = map(int, input().split())
print(CRT(n, a, b))
if __name__ == '__main__':
main()
相关推荐
评论
共 1 条评论,欢迎与作者交流。
正在加载评论...