返回顶部

AtCoder Regular Contest 124 C - LCM of GCDs (记忆化搜索)

  • 题意:有两个容器\(x\)\(y\),\(n\)对数\(a[i]\)\(b[i]\),每次选一对数将\(a[i]\)或者\(b[i]\)放入容器\(x\)\(y\)中,全部放完后将\(x\)\(y\)中所有数求gcd,然后得到的两个数求lcm,问能得到的最大lcm是多少.

  • 题解:这题的\(n\)给的很小,但是直接dfs肯定是不行的,因为每次都是求gcd,所以可考虑每层搜索的时候记忆化一下,如果搜到某一层的时候容器内的两个数已经出现过了,那么直接return即可.

  • 代码:

    #include <bits/stdc++.h>
    #define ll long long
    #define fi first
    #define se second
    #define pb push_back
    #define me memset
    #define rep(a,b,c) for(int a=b;a<=c;++a)
    #define per(a,b,c) for(int a=b;a>=c;--a)
    const int N = 1e6 + 10;
    const int mod = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    using namespace std;
    typedef pair<int,int> PII;
    typedef pair<ll,ll> PLL;
    ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
    ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}
    
    int n;
    ll a[N],b[N];
    vector<map<PLL,ll>> dp(N);
    
    ll dfs(int u,ll xa,ll xb){
        if(dp[u-1][make_pair(xa,xb)]) return dp[u-1][make_pair(xa,xb)];
        if(u==n+1) return dp[u-1][make_pair(xa,xb)]=lcm(1ll*xa,1ll*xb);
        ll res1=dfs(u+1,gcd(xa,a[u]),gcd(xb,b[u]));
        ll res2=dfs(u+1,gcd(xa,b[u]),gcd(xb,a[u]));
        return dp[u-1][make_pair(xa,xb)]=max(res1,res2);
    }
    
    int main() {
        ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
        cin>>n;
        rep(i,1,n) cin>>a[i]>>b[i];
    
        cout<<dfs(2,a[1],b[1])<<'\n';
    
        return 0;
    }
    
    
posted @ 2021-07-28 01:05  Rayotaku  阅读(197)  评论(0编辑  收藏  举报