也不知道是哪个国家的区域赛,感觉欧洲的区域赛可做题貌似很多,然而实力不够,很多可做题没有做完。
这题是给一个序列,求所有区间所得的gcd的不同值有多少,HDU上好像也有类似的题,不过好像更难一点,这题是考虑到当你确定了一个右端点,去不断扩展左端点得到不同的gcd 的时候,得到不同的gcd,那么一定会gcd/2以上,那么对于一个确定的右端点,拓展左端点得到的所有不同的gcd个数不超过log(a[r])个,这样右端点向右挪动一位的时候,只要和之前所有不同的gcd比较求一蛤gcd,然后去掉重复gcd就行了,不同gcd是按从小到大存在vector里面的,所以直接for循环即可。
复杂度为n(logn)^2不过这题卡空间,最后确定所有不同的值的时候只能用set,不能放vector里面unique一蛤,倒是不卡时间。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int maxn = 500005;
int n;
LL a[maxn];
vector<LL>Q[maxn];
set<LL>ans;
inline LL gcd(LL a,LL b){
if(!b)return a;
return gcd(b,a%b);//return b?gcd(b,a%b):a;
}
int main(){
while(~scanf("%d",&n)){
for(int i=1;i<=n;++i){
scanf("%lld",a+i);
Q[i].clear();
}
Q[1].push_back(a[1]);
for(int i=2;i<=n;++i){
LL x=1e18+10;
for(int j=0;j<Q[i-1].size();++j){
LL t=gcd(Q[i-1][j],a[i]);
if(x!=t){
Q[i].push_back(t);
x=t;
}
}
if(x!=a[i])Q[i].push_back(a[i]);
}
ans.clear();
for(int i=1;i<=n;++i){
for(int j=0;j<Q[i].size();++j)
ans.insert(Q[i][j]);//ans.push_back(Q[i][j]);
}
//sort(ans.begin(),ans.end());
//int res=unique(ans.begin(),ans.end())-ans.begin();
printf("%d\n",(int)ans.size());
}
return 0;
}
376

被折叠的 条评论
为什么被折叠?



