ACM/ICPC Indonesia National Contest 2007
Problem B
GCD!
Time Limit: 1sThe greatest common divisor of two numbers is defined as the largest integer that divides both numbers without leaving any reminder. For example, the greatest common divisor of 8 and 12, written as GCD(8,12) is 4, as 4 is the largest integer that divides both 8 and 12 (the common divisors of 8 and 12 are 1, 2, and 4).
Meanwhile, the factorial of a natural number is the product of all positive integers less than or equal to that number. For example, the factorial of 5, written as 5! is 1*2*3*4*5, which equals to 120. By convention, 0! is 1.
Given two integers, n and k, you should find the greatest common divisor of n! and k. For example, if n = 3 and k = 10, then GCD(n!,k) = GCD(3!,10) = GCD(1*2*3,10) = GCD(6,10) = 2. Write a program to find this number!
Input
Each line contains two integers, n (0 <= n <= 1,000,000,000) and k (1 <= k <= 1,000,000,000) respectively.Output
For each line of input, output one line containing the GCD of n! and k.Sample Input
3 10 10 240 12 364 100 2351 629 163547
Sample Output
2 240 28 1 67
Problem Setter: Suhendry Effendy
Pembahasan Problem B - GCD!
Hitunglah GCD(n!,k)
GCD (Greatest Common Divisor) dalam bahasa Indonesia adalah FPB (Faktor Persekutuan Terbesar). Untuk mencari GCD(A,B) anda bisa memfaktorisasi A dan B dalam bentuk faktor-faktor prima mereka, dan kemudian memilih faktor berpangkat paling kecil dan mengalikannya kembali.
Contoh: A = 543312 B = 24570 GCD(A,B) = ? Kita bisa faktorisasi A dan B menjadi faktor prima mereka: A = 543312 = 2^4 * 3^2 * 7^3 * 11 B = 24570 = 2^1 * 3^3 * 5^1 * 7^1 * 13 Berikutnya, untuk setiap faktor prima yang bersekutu (common) antara A dan B, ambil yang berpangkat lebih kecil, kalikan semuanya, itulah hasil GCD(A,B): GCD(A,B) = 2^1 * 3^2 * 7^1 = 126
Ok, itu gampang... tapi pertanyaannya bukan GCD(N,K) tetapi GCD(N!,K). Bagaimana sekarang?
Untuk ini, anda perlu jurus baru:
Cara menghitung banyaknya faktor X di dalam N faktorial.Setelah anda tahu jurus ini, sisanya sama seperti cara diatas:
Ada cara cepat menghitung hal tersebut, anda bisa lihat artikelnya disini. (blum sempet nyari, internet bapuk)
Untuk setiap faktor prima P dari K, anda cari ada berapa faktor prima P dalam N!Silahkan lihat code dibawah untuk lebih jelasnya.
Lalu ambil yang berpangkat terkecil, kalikan ke dalam hasil akhir.
Ada satu trik lagi untuk menghindari time limit dalam pencarian faktor prima P dari K:
Carilah hanya sampai square-root dari K
Karena lebih dari itu, K sudah pasti bilangan prima.
#include <stdio.h> // ini adalah jurus baru yang dimaksud diatas: // menghitung jumlah faktor x dalam n! int factorialPower(int n, int x){ int res = 0; while (n>0){ res += n/x; n /= x; } return res; } int main(){ int n, k, i, p; while (scanf("%d %d",&n,&k)!=EOF){ int result = 1; // GCD dari 2 bilangan positive apapun minimal adalah 1 // kita hanya perlu looping p dari 2 .. sqrt(k) // untuk mencari faktor-faktor prima p dari k. for (p=2; p*p <= k; p++){ int pPower = 0; while (k % p == 0){ k /= p; // p disini adalah bilangan prima di penjelasan diatas pPower++; // mencari berapa banyak faktor p dalam k } // memilih faktor yang berpangkat lebih kecil antara faktor-faktor dari k // dengan faktor-faktor dari n!, tampung pangkat terkecilnya di pPower if (pPower > factorialPower(n,p)) pPower = factorialPower(n,p); // kalikan p ke hasil sebanyak pangkat terkecil yang bersekutu (pPower) for (i=0; i<pPower; i++) result *= p; } // sisa k disini adalah bilangan prima (berpangkat 1) dan kalau k lebih kecil // atau sama dengan n, maka k termasuk bagian dari GCD if (k <= n) result *= k; printf("%d\n",result); } }
No comments:
Post a Comment