[The 2017 BAPC]Question C-Collatz Conjecture--GCD+Optimized Deduplication

Keywords: less

Title: Give you a sequence of size n, let you ask for all the sub-strings of GCD, find out the maximum number of different GCD.

Idea: Use set - tmp to maintain all GCDs to the last element of the current substring, and set - ans to save all kinds of GCDs.
Analyse why it won't be timed out. At first, I thought the algorithm was very violent. I thought it was O(n^2 * logn).
In fact, we guess the most violent situation is, 1, 2, 4, 8, 16,... 2^n This set of data, we would think
1 <= n <= 5e5, so it must be very violent! Actually! No
Why? Because - element ai is in the range of [1,1e18], 2 ^ n <= 10 ^ 18
Two times log2 can be converted --> n <= 18log2 (10), which is about 60, much less than 5e5, so the complexity of the algorithm is almost O(n*18log2(10) * logn).

AC Code: Copy Super ORZ

#include<bits/stdc++.h>
using namespace std;
#define pb                          push_back
#define sz(x)                       int(x.size()-1)
#define all(x)                      x.begin(),x.end()
#define rep(i,s,e)                  for (int i=s;i<=e;i++)
#define rev(i,s,e)                  for (int i=e;i>=s;i--)
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int MAXN = 5e5 + 5;
LL gcd(LL a,LL b)
{
    if(!b) return a;
    else return gcd(b,a%b);
}
set<LL> tmp1,tmp2,ans;
set<LL> ::iterator it;
LL a[MAXN];
int main()
{
    #ifdef LOCAL
    freopen("in.txt","r",stdin);
    #endif
    ios_base::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    int n;
    cin>>n;
    rep(i,1,n) cin>>a[i];
    int f = 0;
    rep(i,1,n)
    {
        if(f)
        {
            tmp1.clear();
            for(it = tmp2.begin();it!=tmp2.end();it++)
            {
                LL x = gcd(a[i],*it);
                tmp1.insert(x);
                ans.insert(x);
            }
            tmp1.insert(a[i]);
            ans.insert(a[i]);
        }
        else
        {
            tmp2.clear();
            for(it = tmp1.begin();it!=tmp1.end();it++)
            {
                LL x = gcd(a[i],*it);
                tmp2.insert(x);
                ans.insert(x);
            }
            tmp2.insert(a[i]);
            ans.insert(a[i]);
        }
        f ^= 1;
    }
    cout<<ans.size()<<endl;
    return 0;
}

Posted by g.grillo on Tue, 05 Feb 2019 13:42:17 -0800