曹冲养猪(中国剩余定理模板题+exgcd求逆元)
source:洛谷P1495
时间限制:1.00s
内存限制:125.00MB
题目描述
自从曹冲搞定了大象以后,曹操就开始捉摸让儿子干些事业,于是派他到中原养猪场养猪,可是曹冲满不高兴,于是在工作中马马虎虎,有一次曹操想知道母猪的数量,于是曹冲想狠狠耍曹操一把。举个例子,假如有16头母猪,如果建了3个猪圈,剩下1头猪就没有地方安家了。如果建造了5个猪圈,但是仍然有1头猪没有地方去,然后如果建造了7个猪圈,还有2头没有地方去。你作为曹总的私人秘书理所当然要将准确的猪数报给曹总,你该怎么办?
输入格式
第一行包含一个整数n (n <= 10) – 建立猪圈的次数,解下来n行,每行两个整数ai, bi( bi <= ai <= 1000), 表示建立了ai个猪圈,有bi头猪没有去处。你可以假定ai,aj互质.
输出格式
输出包含一个正整数,即为曹冲至少养母猪的数目。
输入1
3
3 1
5 1
7 2
输出1
16
题解
先了解一下中国剩余定理(巨佬请直接跳过 )
好了接下来你已经明白答案显然就是
其中
而
t
i
t_i
ti可以用
e
x
g
c
d
exgcd
exgcd求出,看到这里这题突然就变得索然无味了
这道题还有几个坑,首先用快速幂求逆元会WA,怀疑是爆LL了,其次对ans取模时要放在下面,若是直接在括号里加上mod(代码46行)也会WA,怀疑也是爆LL了……
代码
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
#include <cstring>
#include <vector>
#include <queue>
#include <map>
#define m_p make_pair
#define p_i pair<int, int>
#define maxn 12
#define maxm 505
#define _for(i, a) for(LL i = 0; i < (a); i++)
#define _rep(i, a, b) for(LL i = (a); i <= (b); i++)
#define outval(a) cout<<#a<<": "<<a<<"\n"
using namespace std;
typedef long long LL;
const LL MAXN = 110;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
typedef vector< double > vec;
typedef vector< vec > mat;
const double eps = 1e-8;
vector<LL> B, M;
LL mod;
void init() {
mod = 1;
}
void exgcd(LL a, LL b, LL&x, LL&y) {//用快速幂求逆元会WA,怀疑数据溢出了
if (!b) { x = 1; y = 0; }
else {
exgcd(b, a % b, y, x);
y -= a / b * x;
}
}
void Crt(vector<LL>&B, vector<LL>M) {
LL ans = 0, x, y;
_for(i, B.size()) {
LL m = mod / M[i];
exgcd(m, M[i], x, y);
ans = (ans + m * x*B[i]) % mod;
ans = (ans + mod) % mod;//放在下面以防止溢出(这道题真的会溢出)
}
cout << ans << "\n";
}
int main() {
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
//freopen("in.txt", "r", stdin);
init();
int n;
cin >> n;
B.resize(n);
M.resize(n);
_for(i, n) cin >> M[i] >> B[i], mod *= M[i];
Crt(B, M);
return 0;
}
/*
*/