ACM-韓信點兵【中國剩餘定理-孫子定理】
題目34---韓信點兵
時間限制:3000 ms | 記憶體限制:65535 KB
難度:1
描述
相傳韓信才智過人,從不直接清點自己軍隊的人數,只要讓士兵先後以三人一排、五人一排、七人一排地變換隊形,而他每次只掠一眼隊伍的排尾就知道總人數了。輸入3個非負整數a,b,c ,表示每種隊形排尾的人數(a<3,b<5,c<7),輸出總人數的最小值(或報告無解)。已知總人數不小於10,不超過100 。
輸入
輸入3個非負整數a,b,c ,表示每種隊形排尾的人數(a<3,b<5,c<7)。例如,輸入:2 4 5
輸出
輸出總人數的最小值(或報告無解,即輸出No answer)。例項,輸出:89
樣例輸入
2 1 6樣例輸出
41
我的答案:
#include<iostream>
usingnamespacestd;
inthanxindianbing(inta,intb,intc){
for(inti=7+c;i<100;i=i+7)
{
if(i%3==a&&i%5==b)
returni;
}
return0;
}
intmain(){
while(1){
inta,b,c;
cin>>a>>b>>c;
if(a<3&&b<5&&c<7)
cout<<hanxindianbing(a,b,c)<<endl;
}
}
標準答案如下:
01.
#include<iostream>
02.
using
namespace
std;
03.
int
main()
04.
{
05.
int
a,b,c;
06.
cin>>a>>b>>c;
07.
int
n=(a*70+b*21+c*15)%105;
08.
if
(n>100||n<10)
cout<<
"No
answer"
<<endl;
09.
else
cout<<n<<endl;
10.
}
這道題用的是中國剩餘定理,也稱孫子定理從而簡化了程式碼,提高了程式的效率。
其實這道題簡化為已知三個互質的數A,B,C除某個數X的餘數a,b,c和這三個互質的數,求這個X的最小值
如果寫成數學公式就是:
X%A=a;
X%B=b;
X%C=c;
解決問題的方法是首先求出一個儘可能小的數 Y ,使得Y分別除以三個質數時,得到的餘數恰好為a,b,c。然後Y再除以三個互質的數的最小公倍數G,餘數即為X。
所以首先要找到這個數Y:
找到這個數Y的方法是先找到三個數M,N,P:M分別除以三個質數時,得到的餘數為a,0,0;N時,餘數為0,b,0;P時,餘數為0,0,c。
如此,Y = M+N+P。就可以得到想要的Y。
然後是找到數M,N,P的方法:
這裡舉例找數M的方法,其它同理:若要使M%B==M%C=0、M%A=a,則M必為B與C的公倍數
所以先求出B與C的公倍數T,然後用T和T的倍數與A相除,直到找到餘數為1的較小值Q(不必要求是最小值,只是儘量小方便運算),則M = Q*a;
同理找出另外兩個較小值R,F,則N=R*b,P=F*c。
所以Y=Q*a+R*b+F*c;
則X=(Q*a+R*b+F*c)%G;
當互質的數的數量變為4個,5個,6個,餘數有變化等情況,皆可運用上述定理。
PS:
1 注意題目是否有解,數與數之間必須互質
2 如果數與數之間非互質,則必須符合實際情況,如 3除餘2,9除餘4的條件是不可能的,因為9除餘4,3除4餘1,而不是餘2,則題目不成立。
3 G必須為最小公倍數