【The 2017 BAPC】C題-Collatz Conjecture ---- GCD+優化去重
阿新 • • 發佈:2019-02-18
題意: 給你一個大小為n的序列,讓你求裡面所有子串的GCD,求裡面最多有多少不同的GCD。
思路: 利用集合set–tmp維護 到當前子串的最後一個元素的所有GCD,set–ans儲存所有不同種類的GCD。
分析一下為什麼不會超時,一開始以為這個演算法很暴力,覺得是O(n^2 * logn)
其實,我們猜想最暴力的情況 即,1 ,2 , 4, 8 ,16,…… ,2^n 這組資料,我們會以為
1<=n<=5e5,這樣子一定非常暴力! 其實!不是!!
為什麼呢?因為——-元素ai 要在[1,1e18]這個範圍內,所以2^n <= 10^18
兩遍同取log2 可以 轉換—–> n<= 18log2(10) 這個 數字約等於60,遠遠小於5e5,所以這個演算法複雜度差不多為O(n*18log2(10) * logn)。
AC程式碼: 臨摹超霸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;
}