眾所周知,我是好人!
所以不會出太難的題,題意很簡單 給你兩個數n和m,問你有多少對正整數對最大公約數是n,最小公倍數是m
最後友情提供解題**(我真是太好人了)
void solve()
}printf("%d\n", ans); }
祝大家ac愉快!最好ak,送某揚兌現諾言^_^
輸入第1行是乙個整數t,表示共t組資料。 接下來是t組資料,每組資料佔1行,每一行有2個整數n,m(1 <= n, m <= 10000000000),兩個數由乙個空格隔開。
結果輸出t行,對應t組資料。(t<=100)
每行輸出這樣的正整數對有多少對(看我多好人,不用你們輸出所有整數對) 3
1 1
7 10086
4 1610
1 題意:這個太明確了.
分析:這個題我們可以這麼想 .假如 p,q 兩數的最大公約數是n,最小公倍數是m,數學好的可以知道 m 其實就是 n 乘以 q,p 各自特有的因子.
那麼 肯定就有 m % n ==0 . 換句話說 如果 m % n !=0 那麼 輸出 就是0;
好,這個時候我們令 k = m / n ; 那麼 對 k 進行 合數分解 因子集合為 s = ;
這個時候 我們把集合s 分為兩部分分別乘到 n 上得到的兩個數 就是 p,q . 注意的是 這兩部分 的任意s 元素都要互質. 不然 假如兩部分的s元素存在一對 有公共因子 c (c≠1);那麼分別乘以n 得到的 p,q 的最大公約數就不是 n, 而是 c*n ;這個不多說,可以證明.
如何使得s 任意分割兩部分都是互質, 那麼我們可以給 集合s 再加乙個屬性,就是對於每個 s元素都只能由乙個質數相乘得來的.並且每個s元素的自身質數都各不相同.那麼無論怎麼分分割,兩部分的任意元素對都是互質的.
那麼分割的種類我們可以看作是,每個元素都有兩種分割方式,乙個是分割到左邊,乙個是分割到右邊 . 那麼總數就是 2 ^ num(s) ; num(s)表示 s集合的元素個數.
再考慮對稱性(即是 3 5 和 5 3 是同一組) 最後結果除以2 就是 2 ^ ( num(s) - 1 );
線性素數篩選和合數分解.
上**:
#includeint a[1000001],b[100000],tot;
void init() //線性素數篩選
}tot=0;
for(i=2;i<1000000;i++)
if(a[i]==0)
b[tot++]=i;
}
int main()
if(m==n)
int ans=1;
for(i=0;i1) ans*=2; //當k大於1的時候,說明 k中還有大於 10 ^ 6的質數. 那麼 ans再乘以乙個2 .
printf("%d\n",ans/2);
}return 0;
}
最大公約數 最小公倍數
求最大公約數最直接的辦法是從兩數中較小數與2之間的所有整數中乙個乙個的找。但這個方法有點浪費。有兩種有名的方法 1.輾轉相除法2.更相減損之術這兩種方法比較有名,而且現在人教版的高中數學中已經介紹了這兩種方法。下面這個是第2個,因為它只需要加減法就可以,效率高。int maxfactor unsig...
最小公倍數 最大公約數
求最小公倍數演算法 最小公倍數 兩整數的乘積 最大公約數 求最大公約數演算法 1 輾轉相除法 有兩整數a和 b a b得餘數c 若c 0,則 b即為兩數的最大公約數 若c 0,則 a b,b c,再回去執行 例如求27和 15的最大公約數過程為 27 15 餘12 15 12餘3 12 3餘0 因此...
最大公約數,最小公倍數
兩個數最大公約數 輾轉相除法 在數學中,輾轉相除法,又稱歐幾里得演算法,是求最大公約數的演算法。兩個整數的最大公約數是能夠同時整除它們的最大的正整數。輾轉相除法基於如下原理 兩個整數的最大公約數等於其中較小的數和兩數的差的最大公約數。例如 用 a,b 來表示a和b的最大公約數。已知a,b,c為正整數...