分火腿
時間限制: 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;
}