Editorial for Bedao Testing Contest 01 - FRAC
Submitting an official solution before solving the problem yourself is a bannable offence.
Author:
Gọi ~G~ là tích các số trong mảng ~a~.
Gọi ~F~ là bội chung nhỏ nhất các số trong mảng ~a~.
Do giá trị ~G~ trong mảng ~a~ có xu hướng tăng nhanh, nên nếu làm thuật toán duyệt để tính ~G~ và ~F~ rồi đem chia thì sẽ bị tràn số ( lớn hơn ~10^{18}~ ).
Thay vì đi tính ~G~ và ~F~ ta sẽ biểu diễn ~G~ và ~F~ dưới dạng thừa số nguyên tố ~X~ và số mũ ~xG~ và ~xF~. Với ~F~ thì thừa số nguyên tố ~X~ có trong ~F~ phải lấy số mũ ~max~ trong các số ~a_i~.
Quan sát phép tính ~\frac{G}{F}~, ta thấy với thừa số nguyên tố là ~X~ có số mũ ở ~G~ là ~xG~ và số mũ ở ~F~ là ~xF~, ~X~ sẽ xuất hiện cả ở trong ~G~ và ~F~ nên kết quả của ~\frac{G}{F}~ mà có thừa số nguyên tố ~X~ sẽ là ~X^{xG-xF}~. Vậy trong trường hợp tổng quát có ~k~ số ~X~ xuất hiện trong cả ~G~ và ~F~ thì đáp án bài toán là:
~X_1^{xG_1-xF_1} \times X_2^{xG_2-xF_2} \times X_3^{xG_3-xF_3} \times ... \times X_k^{xG_k-xF_k}~
Ta thấy sẽ không tồn tại ~xG - xF < 0~ vì với thừa số nguyên tố ~X~ thì ~xF = max(xG)~ cho nên ~xF \leq xG~.
Code mẫu
#include <iostream> #include <stdio.h> #include <vector> #include <cmath> #include <math.h> #include <map> #include <algorithm> #include <set> #include <bitset> #include <queue> #include <cstring> #include <stack> #include <iomanip> #include <assert.h> #define _(x) (1LL<<(x)) #define BIT(x,pos) (((x)>>(pos)) & 1LL) #define turn_all(x) (_(x)-1LL) #define bitCnt(x) __builtin_popcountll(x) #define name "test" #define nameTask "" #define fastIO ios::sync_with_stdio(false); cin.tie(0); using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; typedef pair<int,int> pii; typedef pair<int,ll> pil; typedef pair<ll, int> pli; typedef pair<ll, ll> pll; typedef vector<int> vi; typedef vector<ll> vll; const int N = 100; const int M = 1E7; int prodPow[M+9], lcmPow[M+9]; int a[N+9]; int n; void factNum(int n,int val, int myPow[N+9]) { for (int i = 2;i <= n; ++i) for (;n % i == 0;) { n /= i; myPow[i] += val; } } ll myPow(ll x,ll y) { ll res = 1; while (y > 0) { if (y & 1) (res = res * x); y >>= 1; (x = x * x); } return res; } void factLCM(int n) { for (int i = 2;i <= n; ++i) { int cnt = 0; for (;n % i == 0;) { n /= i; ++cnt; } lcmPow[i] = max(lcmPow[i],cnt); } } void solveOne() { for (int i = 1;i <= n; ++i) factNum(a[i],1, prodPow); for (int i = 1;i <= n; ++i) factLCM(a[i]); for (int i = 1;i <= M; ++i) prodPow[i] -= lcmPow[i]; ll ans = 1; for (int i = 1;i <= M; ++i) (ans *= myPow(i,prodPow[i])); cout<<ans<<"\n"; } int myGCD(int a,int b) { while (b > 0) { int r = a % b; a = b; b = r; } return a; } void solveTwo() { int G = 1; for (int i = 1;i <= n; ++i) G *= a[i]; int F = a[1]; for (int i = 2;i <= n; ++i) F = ((F * a[i]) / (myGCD(F,a[i]))); cout<<G/F; } signed main() { fastIO cin>>n; if (n == 0) return cout<<"impossible", 0; for (int i = 1;i <= n; ++i) { cin>>a[i]; if (a[i] == 0) return cout<<"impossible" ,0; } solveOne(); }
Comments