223. 阿九大战朱最学

题目链接

223. 阿九大战朱最学

自从朱最学搞定了 QQ 农场以后,就开始捉摸去 QQ 牧场干些事业,不仅在自己的牧场养牛,还到阿九的牧场放牛!

阿九很生气,有一次朱最学想知道阿九牧场奶牛的数量,于是阿九想狠狠耍朱最学一把。

举个例子,假如有 \(16\) 头奶牛,如果建了 \(3\) 个牛棚,剩下 \(1\) 头牛就没有地方安家了。

如果建造了 \(5\) 个牛棚,但是仍然有 \(1\) 头牛没有地方去,然后如果建造了 \(7\) 个牛棚,还有 \(2\) 头没有地方去。

你作为阿九的私人秘书理所当然要将准确的奶牛数报给阿九,你该怎么办?

输入格式

第一行包含一个整数 \(n\) 表示建立牛棚的次数。

接下来 \(n\) 行,每行两个整数 \(a_i, b_i\),表示建立了 \(a_i\) 个牛棚,有 \(b_i\) 头牛没有去处。

你可以假定不同 \(a_i\) 之间互质。

输出格式

输出包含一个正整数,即为阿九至少养奶牛的数目。

数据范围

\(1 \le n \le 10\),
\(1 \le a_i,b_i \le 1200000\)
所有 \(a_i\) 的乘积不超过 \(10^{12}\)

输入样例:

3
3 1
5 1
7 2

输出样例:

16

解题思路

中国剩余定理:设 \(m_1, m_2, \cdots, m_n\) 是两两互质的整数, \(m=\prod_{i=1}^n m_i, M_i=m / m_i, t_i\) 是线性同余 方程 \(M_i t_i \equiv 1\left(\bmod m_i\right)\) 的一个解。对于任意的 \(n\) 个整数 \(a_1, a_2, \cdots, a_n\), 方程组

\[\left\{\begin{array}{c} x \equiv a_1\left(\bmod m_1\right) \\ x \equiv a_2\left(\bmod m_2\right) \\ \vdots \\ x \equiv a_n\left(\bmod m_n\right) \end{array}\right. \]

有整数解, 解为 \(x=\sum_{i=1}^n a_i M_i t_i\)

(来自蓝书)证明:因为 \(M_i=m / m_i\) 是除 \(m_i\) 之外所有模数的倍数, 所以 \(\forall k \neq i, a_i M_i t_i \equiv 0\) \(\left(\bmod m_k\right)\) 。又因为 \(a_i M_i t_i \equiv a_i\left(\bmod m_i\right)\), 所以代入 \(x=\sum_{i=1}^n a_i M_i t_i\), 原方程组成立

求出一个特解 \(x\),可得其通解为 \(x+k m(k \in \mathbb{Z})\)

  • 时间复杂度:\(O(mlogn)\)

代码

// Problem: 阿九大战朱最学
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/225/
// Memory Limit: 64 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=15;
int n,a[N],b[N];
LL M=1,m[N],res=0;
LL exgcd(LL a,LL b,LL &x,LL &y)
{
	if(!b)
	{
		x=1,y=0;
		return a;
	}
	LL d=exgcd(b,a%b,y,x);
	y-=a/b*x;
	return d;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
    	scanf("%d%d",&a[i],&b[i]);
    	M*=a[i];
    }
    for(int i=1;i<=n;i++)
    {
    	m[i]=M/a[i];
    	LL x,y;
    	exgcd(m[i],a[i],x,y);
    	res+=m[i]*x*b[i];
    }
    cout<<(res%M+M)%M;
    return 0;
}
posted @ 2022-11-16 20:25  zyy2001  阅读(41)  评论(0编辑  收藏  举报