AcWing 1298. 曹衝養豬(中國剩餘定理)

Chemin Du Retour發表於2020-10-28

題目

自從曹衝搞定了大象以後,曹操就開始琢磨讓兒子幹些事業,於是派他到中原養豬場養豬,可是曹衝很不高興,於是在工作中馬馬虎虎,有一次曹操想知道母豬的數量,於是曹衝想狠狠耍曹操一把。

舉個例子,假如有 16 頭母豬,如果建了 3 個豬圈,剩下 1 頭豬就沒有地方安家了;如果建造了 5 個豬圈,但是仍然有 1 頭豬沒有地方去;如果建造了 7 個豬圈,還有 2 頭沒有地方去。

你作為曹總的私人祕書理所當然要將準確的豬數報給曹總,你該怎麼辦?

輸入格式

第一行包含一個整數 n,表示建立豬圈的次數;

接下來 n 行,每行兩個整數 ai bi ,表示建立了 ai 個豬圈,有 bi 頭豬沒有去處。

你可以假定 ai, aj 互質。

輸出格式

輸出僅包含一個正整數,即為曹衝至少養豬的數目。

資料範圍

1 < n <10
1 < b_i < a_i < 1100000
所有a_i的乘積不超過 10^18

輸入樣例:

3
3 1
5 1
7 2

輸出樣例:

16

題解

中國剩餘定理裸題,
對於x mod m1 = a1 , x mod m2 = a2 … x mod mn = an,
一 . 設M = m1 * m2 * … mn; m[i] = M / mi , 設 m[i] * t[i] mod mi = 1;
二 : x += a[i] * m[i] * t[i]; ( 1<= i <= n);
m[i]已知,M已知,那麼m[i] * ti mod mi = 1 用擴充套件歐幾裡求得滿足得ti;, 然後累加即可
最後記得ans % M,這樣才是最小的
對於這個題來說,mi * ti mod a[i] = 1,求得 ti .

int n;
ll a[MAXN],t[MAXN],b[MAXN];
ll M;

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);
	M = 1;
	for(int i=1;i<=n;i++){
		scanf("%lld %lld",&a[i],&b[i]);
		M *= a[i];
	}
	ll ans = 0;
	for(int i=1;i<=n;i++){
		ll mi = M / a[i];
		ll ti,y;
		exgcd(mi,a[i],ti,y);
		ans += b[i]*mi*ti;
	}
	ans = (ans % M + M) % M; 
	printf("%lld\n",ans);
	return 0;
}

相關文章