hihoCoder-week144:機會渺茫

題目描述:

小Hi最近在追求一名學數學的女生小Z。小Z其實是想拒絕他的,但是找不到好的說辭,於是提出了這樣的要求:對於給定的兩個正整數N和M,小Hi隨機選取一個N的約數N',小Z隨機選取一個M的約數M',如果N'和M'相等,她就答應小Hi。

小Z讓小Hi去編寫這個隨機程序,到時候她review過沒有問題了就可以抽籤了。但是小Hi寫着寫着,卻越來越覺得機會渺茫。那麼問題來了,小Hi能夠追到小Z的機率是多少呢?


解決思想:

假設N有Nnum個約數,M有Mnum個約數,N和M共有same個相同的約數。對於一個公共約數,在N中抽取到它的概率爲1/Nnum,M爲1/Mnum,所以同時抽取到這個公共約數的概率爲1/(Nnum*Mnum)。一共有same個公共約數,則總概率爲same個1/(Nnum*Mnum)相加,則概率爲same/(Nnum*Mnum)。

如何求解same:same即爲N和M最大公因數的約數個數。


需要實現的算法:

1.給定一個數,求解它的約數總個數。

2.給定兩個數,求解它們的最大公因數。


實現算法原理:

1.O(sqrt(N))求約數個數法

比如要求解36的約數,我們可以把36如下分解:

36=1*36

36=2*18

36=3*12

36=4*9

36=6*6

注意我們只寫出了小於等於sqrt(36)個等式就找到了它(36)所有的約數,共九個。因爲當我們找到A的約數B時,也可默認得到A/B是A的另一個約數(如果A/B和B 不相等的話),這樣我們就想到,在計算N的約數個數時可以只檢查前sqrt(N)個數是否爲N的約數,若爲,則約數個數加2(若約數的平方等於N時再-1)

具體實現代碼如下:

long divisor_num(long num){
    long i;
    long result=0;
    for(i=1;i<=sqrt(num);i++){
        if(!(num%i)){
            result+=2;
            if(i*i==num)
                result--;
        }
    }
    return result;
}


2.使用Euclidean algorithm求解最大公因數

假設求解a、b的公因數gcd,且a>=b。易知,gcd也是a、a-b的公因數,那麼如何證明gcd是最大公因數呢,我是這樣想的。

因爲gcd是a、b的最大公因數,所以a=m*gcd,b=n*gcd,m和n互質(即m和n的最大公約數爲1,gcd已經完全從m、n抽取了相同的約數)。

兩式相減得到a-b=(m-n)*gcd,若m-n和m互質,那麼gcd也就是a與a-b的最大公約數。由於m和n互質,那麼顯然m-n和m互質。

由於gcd是a、a-b的最大公因數,那麼顯然gcd也是a、a%b(即a-kb)的最大公因數。


具體實現代碼如下:

long find_gcd(long x,long y){
    return y==0?x:find_gcd(y,x%y);
}
當x<y時,迭代下一步就會調換xy的位置。

當每一次計算的餘數都會減小,所以最後y一定等於0從而算出最大公約數x。



算法整體代碼:

#include <iostream>
#include <cmath>
using namespace std;

long divisor_num(long num){
    long i;
    long result=0;
    for(i=1;i<=sqrt(num);i++){
        if(!(num%i)){
            result+=2;
            if(i*i==num)
                result--;
        }
    }
    return result;
}

long find_gcd(long x,long y){
    return y==0?x:find_gcd(y,x%y);
}

int main()
{
    long N,M;
    cin>>N>>M;
    long Nnum=divisor_num(N);
    long Mnum=divisor_num(M);
    long same=divisor_num(find_gcd(N,M));
    long tmp=find_gcd(Nnum*Mnum,same);
    cout<<Nnum*Mnum/tmp<<" "<<same/tmp;
    return 0;
}




發佈了39 篇原創文章 · 獲贊 0 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章