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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章