Nikita and LCM题解

题目大意

给你一个数组 $ a $,令 $ t $ 为 $ a $ 的子序列且 $ t $ 中所有数的最小公倍数 $ \notin a $ 求 $ t $ 数组中最多有多少个数。

思路

非常明显这是一道数学题,对于数组 $ a $ 我们首先从小到大拍一个序,然后我们可以求出 $ a $ 中所有数的最大公倍数,如果这个公倍数 $ \not= a_n $ 所以答案为 $ n $,否者可以证明 $ a_1,a_2,\dots,a_n $ 都为 $ a_n $ 的因子。

我们可以枚举 $ a_n $ 的每一个因子 $ d $ 如果 $ d $ 没有在 $ a $ 数组中出现过,那么我们就去 Check $ d $,而 Check 的内容为判断 $ a $ 数组里面的数是否能组成 $ d $,思路大致就是这样,小细节就看代码了。

Code:

#include <algorithm>
#include <iostream>
#include <math.h>
#include <string.h>
#include <queue>
#include <stdio.h>
#include <map>
#define ll long long
#define prt printf
#define int long long
#define sc(ppt) scanf("%lld" , &ppt)
using namespace std;

int t , n , ans = 0 , a[2005];
map<int , int> G;

int lcm(int a , int b){
	return a * b / __gcd(a , b);
}

void check(int d){
	int cnt = 0 , res = 1;
	for(int i=1 ; i<=n ; i++){
		if(a[i] == a[n]) break;
		if(d % a[i] == 0){
			++ cnt;
			res = lcm(res , a[i]);
		}
	}
	if(res == d) ans = max(ans , cnt); // 打一个擂台 
}

void solve(){
	int res = 1;
	for(int i=1 ; i<=n ; i++){
		res = lcm(res , a[i]);
		if(res > a[n]){
			ans = n ;
			break;
		}
	}
	if(ans != n && !G.count(res)) ans = n;
	for(int i=1 ; i*i<=a[n] ; i++){
		if(a[n] % i != 0) continue;
		if(!G.count(i)){ check(i);}
		if(i * i != a[n] && !G.count(a[n] / i)) check(a[n] / i);
	}
}	

signed main(){
	sc(t) ; while(t --){
		ans = 0 ; G.clear() ;	
		sc(n) ; for(int i=1 ; i<=n ; i++){
			sc(a[i]) ; G[a[i]] =  1;
		}
		sort(a + 1 , a + n + 1) ; solve() ;
		prt("%lld\n" , ans); 
	}
	return 0;
}
posted @ 2024-05-30 21:17  CaoSheng  阅读(32)  评论(0)    收藏  举报