题目大意:
给你
n
n
n个数,每个数保证约数个数不超过
7
7
7个。问你从中选出若
干个数的乘积是完全平方数,最少要选择多少个数?,不存在输出-1.
题目思路:
1.每个数约数不超过7个
→
\rightarrow
→每个数最多只有两个不同的质因子
n
=
p
1
a
1
p
2
a
2
.
.
.
p
n
a
n
n=p_1^{a1}p_2^{a2}...p_n^{an}
n=p1a1p2a2...pnan
Number of divisors
=
(
a
1
+
1
)
∗
(
a
2
+
1
)
.
.
∗
(
a
n
+
1
)
≤
7
\text{Number of divisors}=(a_1+1)*(a_2+1)..*(an+1)\leq7
Number of divisors=(a1+1)∗(a2+1)..∗(an+1)≤7
那么可以解除
n
≤
2
n\leq2
n≤2
- 我知道平方数里面的质因子的指数都是偶数,那么我们先把偶数的质因子给去掉那么每个质因子要么没有,要么只剩下一个那么 n n n可以表示为 n = p 1 × p 2 n=p_1\times p_2 n=p1×p2我们对 p 1 和 p 2 p_1和p_2 p1和p2直接连接无向边,那么要使得是是完全平方数,就是p1,p2,p3要出现偶数个 → \rightarrow →每个点的度数是偶数
- 我们要求最小那么每个点的度数最好为2,那么本质上就是找最小环,每个点的度数都是 2 2 2
- 无向图最小环 → F l o y e d O ( n 3 ) \rightarrow\;Floyed\;O(n^3) →FloyedO(n3)直接T飞了!!
- 我们观察一下图结构 p 1 ≤ n , p 2 > n p_1\leq\sqrt n,p_2>\sqrt n p1≤n,p2>n就是小点和大点交错连边
- 那么我们可以枚举起点,用 b f s bfs bfs去找最小环 , b f s bfs bfs找最小环是保证起点一定在环上面,但是不能枚举所有的点,我们发现 小 点 连 大 点 , 就 是 一 条 边 的 两 端 肯 定 是 一 个 ≥ n , 一 个 小 于 n 小点连大点,就是一条边的两端肯定是一个\ge\sqrt n,一个小于\sqrt n 小点连大点,就是一条边的两端肯定是一个≥n,一个小于n
- 那么我们只要枚举小于
n
\sqrt n
n就可以了
也
就
最
多
也
就
1000
也就最多也就1000
也就最多也就1000
那么就可以A了
AC code
#include <bits/stdc++.h>
#define mid ((l + r) >> 1)
#define Lson rt << 1, l , mid
#define Rson rt << 1|1, mid + 1, r
#define ms(a,al) memset(a,al,sizeof(a))
#define log2(a) log(a)/log(2)
#define lowbit(x) ((-x) & x)
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define INF 0x3f3f3f3f
#define LLF 0x3f3f3f3f3f3f3f3f
#define f first
#define s second
#define endl '\n'
using namespace std;
const int N = 2e6 + 10, mod = 1e9 + 9;
const int maxn = N;
const long double eps = 1e-5;
const int EPS = 500 * 500;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
typedef pair<double,double> PDD;
template<typename T> void read(T &x) {
x = 0;char ch = getchar();ll f = 1;
while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
template<typename T, typename... Args> void read(T &first, Args& ... args) {
read(first);
read(args...);
}
inline void out(int x) {
if (x > 9) out(x / 10);
putchar(x % 10 + '0');
}
vector<int> edge[maxn];
int dist[maxn], fa[maxn];
int ans = INF;
void bfs(int u) {
memset(dist, INF, sizeof(dist));
dist[u] = 0;
queue<int> q;
q.push(u);
while (!q.empty()) {
int u = q.front();
q.pop();
for (int i = 0; i < edge[u].size(); i++) {
int v = edge[u][i];
if (v != fa[u]) {
if (dist[v] != INF) ans = min(ans, (dist[u] + dist[v] + 1));
else fa[v] = u, dist[v] = dist[u] + 1, q.push(v);;
}
}
}
}
int main() {
int n, x;
read(n);
for (int i = 0; i < n; i++) {
read(x);
for (int i = 2; i <= sqrt(x); i++) {
while (x % (i * i) == 0) x /= i * i;
}
if (x == 1) {
out(1);
return 0;
}
int u = x, v = 1;
edge[u].push_back(v);
edge[v].push_back(u);
for (int i = 2; i <= sqrt(x); i++) {
if (x % i == 0) {
u = x / i, v = i;
edge[u].push_back(v);
edge[v].push_back(u);
}
}
}
for (int i = 1; i <= sqrt(maxn); i++) bfs(i);
if (ans != INF) out(ans);
else printf("-1");
return 0;
}