NOIP歡樂模擬賽 分火腿 gcd與lcm

分火腿

時間限制: 1 Sec 內存限制: 64 MB

題目描述

小月言要過四歲生日了,她的媽媽爲她準備了n根火腿,她想將這些火腿均分給m位小朋友,所以她可能需要切火腿。爲了省事,小月言想切最少的刀數,使這n根火腿分成均等的m份。請問最少要切幾刀?

輸入

第一行一個整數T,表示有T組數據。
接下來T組數據,每組共一行,有兩個數字n,m。

輸出

每組數據一行,輸出最少要切的刀數。

樣例輸入

3
2 6
3 4
6 2

樣例輸出

4
3
0

gcd與lcm

  • 對於這n段火腿,要想讓m個人平分,那麼我們每個人都需要分到n/m,所以我們需要切m-1次,但是這切的地方有可能剛好與這n段火腿中間重合,這時候我們就不需要再切這一次了

  • 重合的地方是n/m和1的最小公倍數,lcm(1,n/m)=n/m/gcd(1,n/m),我們讓gcd裏面都乘上m,外面再除以m,可得n/m/gcd(m,n)/m,化簡得n/gcd(n,m),然後我們再用n除以這些重合即可得到重合的個數,得到gcd(n,m),又因爲最後一個點重複判斷,所以我們再減去一即可

  • 最後的答案就是保底的m-1次減去重合的gcd(n,m)-1次得m-gcd(n,m)次

AC代碼

#include<cstdio>
using namespace std;
int T,n,m;
inline int read() {
	int x=0,cf=1;
	char ch=getchar();
	while(ch<'0'||ch>'9') {
		if(ch=='-') cf=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9') {
		x=(x<<3)+(x<<1)+(ch^48);
		ch=getchar();
	}
	return x*cf;
}
inline int gcd(int A,int B) {
	return !B?A:gcd(B,A%B);
}
int main() {
	T=read(); while(T--) {
		n=read(),m=read();
		printf("%d\n",m-gcd(n,m));
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章