[ARC122E]Increasing LCMs

Posted Arextre

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[ARC122E]Increasing LCMs相关的知识,希望对你有一定的参考价值。

[ARC122E]Increasing LCMs

壹、题目描述 ¶

传送门 to Atcoder.

贰、题解 ¶

之后做这道题感觉很简单,就是不知道考试的时候自己能否想到。

考虑从后往前填 —— 首先考虑填限制最大的位置

假设当前到第 \\(x\\) 位,还未使用的数集为 \\(A\'\\),那么,一个数字 \\(a_i\\in A\'\\) 能够被放到第 \\(x\\) 位上当且仅当

\\[\\gcd(\\text{lcm}(a_j),a_i)< a_i(a_j\\in A\'\\and a_j\\neq a_i) \\]

但是一个位置上可能出现多个满足条件的数,选择哪一个?任意取一个就好了!若有多个数同时满足,那么他们相互之间,在质因数分解下,一定相互都会存在某个自己的因数多于其他数字的该因数,即无论谁先放,都不能将剩下的数的因数覆盖完,又即无论谁先放,总会让 \\(\\rm lcm\\) 出现增加的部分。

当然,如果没有这样的数,就拜拜了。

然后?直接 \\(\\mathcal O(n^3\\log n)\\) 的暴力就解决了......

只不过发现上面的 \\(\\rm lcm\\) 会爆 \\(\\rm long\\;long\\),但是我们可以找到等价形式:

\\[(*)\\Leftrightarrow\\text{lcm}(\\gcd(a_j,a_i))< a_i(a_j\\in A\'\\and a_j\\neq a_i) \\]

做完了,挺暴力的。

叁、参考代码 ¶

#include<cstdio>
#include<iostream>
#include<vector>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std;

// #define NDEBUG
#include<cassert>

namespace Elaina{
    #define rep(i, l, r) for(int i=(l), i##_end_=(r); i<=i##_end_; ++i)
    #define drep(i, l, r) for(int i=(l), i##_end_=(r); i>=i##_end_; --i)
    #define fi first
    #define se second
    #define mp(a, b) make_pair(a, b)
    #define Endl putchar(\'\\n\')
    #define mmset(a, b) memset(a, b, sizeof a)
    typedef long long ll;
    typedef pair<int, int> pii;
    typedef pair<ll, ll> pll;
    template<class T>inline T fab(T x){ return x<0? -x: x; }
    template<class T>inline void getmin(T& x, const T rhs){ x=min(x, rhs); }
    template<class T>inline void getmax(T& x, const T rhs){ x=max(x, rhs); }
    template<class T>inline T readin(T x){
        x=0; int f=0; char c;
        while((c=getchar())<\'0\' || \'9\'<c) if(c==\'-\') f=1;
        for(x=(c^48); \'0\'<=(c=getchar()) && c<=\'9\'; x=(x<<1)+(x<<3)+(c^48));
        return f? -x: x;
    }
    template<class T>inline void writc(T x, char s=\'\\n\'){
        static int fwri_sta[1005], fwri_ed=0;
        if(x<0) putchar(\'-\'), x=-x;
        do fwri_sta[++fwri_ed]=x%10, x/=10; while(x);
        while(putchar(fwri_sta[fwri_ed--]^48), fwri_ed);
        putchar(s);
    }
}
using namespace Elaina;

const int maxn=100;

ll a[maxn+5];
int used[maxn+5], n;

ll ans[maxn+5];

ll gcd(ll a, ll b){
    return b? gcd(b, a%b): a;
}

signed main(){
    n=readin(1);
    rep(i, 1, n) a[i]=readin(1ll);
    drep(p, n, 1){
        rep(i, 1, n) if(!used[i]){
            ll lcm=1, d;
            rep(j, 1, n) if(j!=i && !used[j]){
                d=gcd(a[i], a[j]);
                lcm=lcm/gcd(lcm, d)*d;
            }
            if(lcm<a[i]){ ans[p]=a[i]; used[i]=1; break; }
        }
        if(!ans[p]) return printf("No\\n"), 0;
    }
    printf("Yes\\n");
    rep(i, 1, n) writc(ans[i], \' \');
    Endl;
    return 0;
}

肆、关键的地方 ¶

为什么要想到从后面填呢?实际上有下列两个因素:

  • 越后面的位置,限制越大,因为必须保证它所含有的因数不能被前面的数字覆盖完;
  • 填后面的数字,对前面的数字没有影响,换句话说,考虑前面的数字对后面填数是有后效性的;

基于这两点,先考虑后面的数是最好的。

以上是关于[ARC122E]Increasing LCMs的主要内容,如果未能解决你的问题,请参考以下文章

[CF1166E] The LCMs Must be Large - 构造

英特尔发布全新高性能显卡品牌Arc,首款显卡将于 2022 年上市

英特尔发布全新高性能显卡品牌Arc,首款显卡将于 2022 年上市

LeetcodeLongest Increasing Subsequence

Longest Increasing Subsequence

Longest Increasing Subsequence