# 演算法課程題解 - 基礎數論 2 # TOJ 3 ## 題目 https://toj.tfcis.org/oj/pro/3/ 有 $t$ 筆測資,每筆測資包含兩個數 $a, b$,求 $a, b$ 的最大公因數 ## 解法 By Koios1143 ### 想法 可以模擬輾轉相除法求解,詳細過程可以參考講義內容。 ### 程式碼 ```cpp= //By Koios1143 #include<iostream> using namespace std; int gcd(int n,int m){ if(n%m == 0){ return m; } return gcd(m, n%m); } int main(){ int t,a,b; cin>>t; while(t--){ cin>>a>>b; cout<<gcd(a,b)<<"\n"; } return 0; } ``` ### 複雜度分析 證明我不知道怎麼證QQ ,不過每筆測資時間複雜度為 $O(log\ {min(a,b)})$ # TOJ 513 ## 題目 https://toj.tfcis.org/oj/pro/513/ 給兩個以 24 進位制表示的時間,包含小時以及分鐘,分別表示開始以及結束的時間,其中保證兩者之間間隔不會超過 24 小時,但是可能跨天,求兩個時間的間隔是幾小時幾分。 ## 解法 By Koios1143 ### 想法 分別算出兩者時間轉換成分鐘,這樣一來如果說結束時間比開始時間來的短,表示過了一天,再加上 $24*60$ 分鐘 最後只需要獲得間隔再轉成小時以及分鐘即可 ### 程式碼 ```cpp= //By Koios1143 #include<iostream> using namespace std; int main(){ int a,b,c,d; cin>>a>>b>>c>>d; int start=a*60+b; int end=c*60+d; if(end-start<0){ end+=24*60; } int res=end-start; cout<<"totally "<< res/60 <<" hours and "<< res%60 <<" minutes.\n"; return 0; } ``` ### 複雜度分析 時間複雜度可記為 $O(1)$ # UVa412 ## 題目 http://domen111.github.io/UVa-Easy-Viewer/?412 給一個集合 $S$ ,從中任意取兩數 $p, q$ 其中該集合所有 $p, q$ 對數記作 $A$, $p, q$ 互質的數量記作 $B$ 求 $\sqrt{6*\frac{A}{B}}$ 四捨五入到小數點後第 $6$ 位 ## 解法 By Koios1143 ### 想法 這裡可以用很暴力的作法完成他 如果兩個數互質,那兩者的最大公因數一定是 $1$ 那麼接下來暴力去看看每一組是不是互質,記錄下來即可 ### 程式碼 ```cpp= //By Koios1143 #include<iostream> #include<iomanip> #include<cmath> using namespace std; int gcd(int n, int m){ if(n%m == 0){ return m; } return gcd(m, n%m); } int main(){ int n; while(cin>>n && n){ int arr[55]; for(int i=0 ; i<n ; i++){ cin>>arr[i]; } int a=0,b=0; for(int i=0 ; i<n ; i++){ for(int j=i+1 ; j<n ; j++){ a++; if(gcd(arr[i], arr[j]) == 1) b++; } } if(b==0) cout<<"No estimate for this data set.\n"; else cout<<fixed<<setprecision(6)<<sqrt((double)(a*6.0/b))<<"\n"; } return 0; } ``` # UVa12468 ## 題目 http://domen111.github.io/UVa-Easy-Viewer/?12468 有一台電視共有 $100$ 臺頻道,由 $0$~$99$,並且是環狀的,也就是說我可以從 $0$ 轉到第 $99$,反之亦同 現在要從頻道 $A$ 轉到頻道 $B$,每次只能轉一臺,正向或是逆向都可,求最少的轉移數 ## 解法 By Koios1143 ### 想法 分別算出正著轉以及逆著轉所需的移動次數,取最小值即可 當我從 $0$ 轉到 $99$ 1. 正轉 $99-0 = 99$ 2. 逆轉 $0-99+100 = 1$ 因為是環,所以當我轉到變成負數,只要在加上 $100$ 就可以回到應該到的位置上了 ### 程式碼 ```cpp= //By Koios1143 #include<iostream> using namespace std; int main(){ int a,b; while(cin>>a>>b){ if(a==-1 && b==-1) break; int forward = b-a; int reverse = a-b; if(forward<0) forward+=100; if(reverse<0) reverse+=100; cout<<min(forward, reverse)<<"\n"; } return 0; } ``` ### 複雜度分析 每筆測資時間複雜度為 $O(1)$ ###### tags: `SCIST 演算法 題解`