Editorial for Bedao Testing Contest 01 - FRAC


Remember to use this editorial only when stuck, and not to copy-paste code from it. Please be respectful to the problem author and editorialist.
Submitting an official solution before solving the problem yourself is a bannable offence.

Author: ntkwan

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

Please read the guidelines before commenting.


There are no comments at the moment.