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;
}