Gym-101666C

也不知道是哪个国家的区域赛,感觉欧洲的区域赛可做题貌似很多,然而实力不够,很多可做题没有做完。

这题是给一个序列,求所有区间所得的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;
}

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值