题目大意
给你一个数组 $ 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;
}
标签:include,int,题解,Nikita,long,数组,ans,LCM,define
From: https://www.cnblogs.com/CaoSheng-blog/p/18223238