【C++、Python】求多個數的最大公約數、最小公倍數+Hankson的趣味題

        分爲【基礎】與【提高】部分,其中【基礎】是求多個數的最大公約數與最小公倍數,【提高】是Hankson問題。(o゚▽゚)o

如果有誤的地方麻煩提出來,感激不盡XDDD 


一、題目

        【基礎】求N個數的最大公約數(gcd)和最小公倍數(lcm)。 

        【提高】Hanks博士是BT(Bio-Tech,生物技術)領域的知名專家,他的兒子名叫Hankson。現在,剛剛放學回家的Hankson正在思考一個有趣的問題。

          今天在課堂上,老師講解了如何求兩個正整數c1和c2的最大公約數和最小公倍數。現在Hankson認爲自己已經熟練地掌握了這些知識,他開始思考一個“求公約數”和“求公倍數”之類問題的“逆問題”,這個問題是這樣的:已知正整數a0,a1,b0,b1,設某未知正整數x滿足:

         1、  x和a0的最大公約數是a1;

         2、  x和b0的最小公倍數是b1。

        Hankson的“逆問題”就是求出滿足條件的正整數x。但稍加思索之後,他發現這樣的x並不唯一,甚至可能不存在。因此他轉而開始考慮如何求解滿足條件的x的個數。請你幫助他編程求解這個問題。

二、解題思路

     【基礎】

       輸入多個整數,先將gcd與lcm取值爲輸入的第一個數字,然後依次輸入數字與gcd、lcm求最大公約數、最小公倍數。此處可用vector代替數組,非常的方便。ヾ(゚∀゚ゞ)

     【提高】

       這個問題解題的關鍵就在於判斷要求的數x是否是a1,b1的共同因數,判斷方法爲:gcd(t/a1,a0/a1)==1 and gcd(b1/b0,b1/t)==1 ,這些參數的意思是t爲a1的因數,b1的約數,如果不清楚可以在草稿紙上驗算試一下。

       此外我們可以知道x肯定不會大於b1而且x肯定能被b1整除,因此可以用判斷b1/x 來減少枚舉次數。再結合求最大公倍數的函數即可解決。

三、流程圖

【基礎】

       【提高】

四、代碼實現

【基礎】

/****

	@Author:Innocence
	@IDE:dev c++
	@OS:win 10
	@Edition:1.0  3/21
			 2.0  3/22
	@Description:求幾個數字的最大公約數,最小公倍數 

****/

#include<iostream>
#include<vector>
using namespace std;
//求最大公約數
int divisor (int a,int b)    
{
	int temp;    //定義整型變量
 	if(a<b) {    //通過比較求出兩個數中的最大值和最小值
    	temp=a;
    	a=b;
    	b=temp;
    }    //設置中間變量進行兩數交換
   	while(b!=0) {    //通過循環求兩數的餘數,直到餘數爲0
    	temp=a%b;
    	a=b;    //變量數值交換
    	b=temp;
    }
  	return a;    //返回最大公約數到調用函數處
}
//求最小公倍數
int multiple (int a,int b)    
{
 	int divisor (int a,int b);    //自定義函數返回值類型
    int temp;
  	temp=divisor(a,b);    //再次調用自定義函數,求出最大公約數
  	return  (a*b/temp);    //返回最小公倍數到主調函數處進行輸出
}
int main()
{
	int n;
	cout << "請輸入數字數:"<<endl;
	cin >> n;
	vector<int> a;    //創建一個vector
	int b;
	int gcd,lcm; 
	for(int i=0;i<n;i++){
		    cout << "請輸入數字:"<<endl;
			cin >> b;
			a.insert(a.begin(),b);
		}
	gcd=a[0];    //令gcd爲輸入的第一個數字
	lcm=a[0];    //令lcm爲輸入的第一個數字
	for(int i=0;i<n;i++){
		gcd=divisor(gcd,a[i]);    //參數順序不影響結果
		lcm=multiple(a[i],lcm);    //參數順序不影響結果
	}
	cout<<"最大公約數:  "<<gcd<<endl;
	cout<<"最小公倍數:  "<<lcm<<endl;
	return 0;
}

【提高】

###    @Author:Innocence
###    @IDE:IDLE (python 3.7 64bit)
###    @OS:win 10
###    @Edition:1.0   3/19
###             2.0   3/2
###             3.0   3/21
###             4.0   3/22
###    @Description:給定最大公約數和最小公倍數求出可能的個數

def gcd(a,b):    #求最大公約數
    if b==0:
        return a
    else:
        return gcd(b,a%b)
def judge(t):   
    if(t%a1!=0):
        return 0
    return gcd(t/a1,a0/a1)==1 and gcd(b1/b0,b1/t)==1    #t和a0、b0約數相同

print('請輸入數據組數:')
n=int(input())    #輸入n組數據
while n!=0:
    n-=1
    print('請輸入數據')
    a0=int(input())    #輸入爲字符轉化成整數
    a1=int(input())
    b0=int(input())
    b1=int(input())
    ans=0
    for x in range (1,b1):    #不可能超過最小公倍數
        if x*x<=b1:
            if b1%x==0:    #判斷是否爲因數
                ans=ans+judge(x)
                if b1/x!=x:    #利用x能被b1整除減少枚舉次數
                    ans=ans+judge(b1/x)
        x+=1
    print('滿足條件的x的個數爲:')
    print(ans)    #返回滿足條件的數字的個數

五、運行結果

【基礎】

【提高】

六、經驗歸納

        這次主要遇到的困難就是提高部分,一開始想到了求他們共同的因數,但是不知道具體該怎麼求,後來在網上了解了數論的部分知識以及參考別人的做法解決了問題。這次我意識到了在寫代碼的時候動筆算也特別重要,以後要多多動筆纔行。(。•́︿•̀。)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章