D. Not Adding 和 埃氏筛

D. Not Adding 和 埃氏筛

题目大意:

​ 一个数组有n个数。每次操作可以将数组中任意两个数字的gcd放入数组中(只有该gcd不在数组内时才能放入)。问最多能做几次操作。

思路和代码:

​ 一个数字和另一个数字的gcd一定不会超过两数字的较小值。所以我们可以枚举1~MAX的所有数字,去判断他是否能尤若干个已经在数组内数字的gcd产生。当然,由若干个数字产生的最大公约数x一定和这些数字有倍数关系。所以可以用类似埃氏筛的做法,枚举x的倍数。

void solve(){
	cin >> n ; 
	Clear() ;
	rep(i , 1 , n){
		cin >> a[i] ;
		vis[a[i]] = 1 ;
		m = max(m , a[i]) ;
	}
	
	rep(i , 1 , m){
		if(vis[i]) continue ;//已经在集合中不用操作 
		
		ll prej = -1 ;//prej表示前若干个数的gcd 
		
		for(ll j = i + i ; j <= m ; j += i){
			if(!vis[j]) continue ;//当枚举的i的倍数j在集合中
			prej = prej == -1 ? j : __gcd(j , prej) ;
			if(prej == i){//就有可能存在他和其他数字gcd等于i的情况 
				ans ++ ; break ;
			}
		} 
		
	}
	cout << ans ;

}
拓展:

这题的枚举方式和埃氏筛很像,时间复杂度是mlogm

bool isprm[N] ;
ll prm[N] ;
ll Esieve(ll n){
	ll res = 0 ;
	isprm[0] = isprm[1] = 1 ;//1表示非质数
	
	for(int i = 2 ; i <= n ; i ++ ){
		if(!isprm[i]){
			prm[++ res] = i ;
			for(int j = i * 2 ; j <= n ; j += i)
				isprm[j] = 1 ;
		}
	}
	cout << res << ":\n" ;
	rep(i , 1 , res) cout << prm[i] << " " ; cout << "\n" ;
}
posted @ 2022-01-16 17:18  tyrii  阅读(96)  评论(0)    收藏  举报