- 题目:

- 思路:
如果一个数 x x x有三个不同的质约数 p 1 , p 2 , p 3 p_1, p_2, p_3 p1,p2,p3,那么这个数至少有8个约数。
这是因为 g c d ( p 1 , p 3 ) = 1 , g c d ( p 2 , p 3 ) = 1 gcd(p_1,p_3)=1, gcd(p_2, p_3)=1 gcd(p1,p3)=1,gcd(p2,p3)=1,那么 g c d ( p 1 ∗ p 2 , p 3 ) = 1 gcd(p_1*p_2, p_3)=1 gcd(p1∗p2,p3)=1,也就是说不可能存在两个质约数的乘积= x x x(否则就会有 p 3 ∣ ( p 1 ∗ p 2 ) , g c d ( p 1 ∗ p 2 , p 3 ) p_3|(p_1*p_2),gcd(p_1*p_2, p_3) p3∣(p1∗p2),gcd(p1∗p2,p3)),再加上1和 x x x就至少有8个约数了。
所以题目的意思是说给出的 a i a_i ai都最多有两个质约数。
所谓完全平方数 x x x,可以理解为对 x x x进行完全质因子分解,每个质因子的出现次数都为偶次。
对 a i a_i ai进行完全质因子分解,只考虑出现奇数次的质因子,由于题目保证 a i a_i ai最多只有两个质约数,也就是出现奇数出的质因子最多只有两个。构造一个图,点的编号都是质数,边权是对应的 a i a_i ai。 x x x分解完后可能为1、1个质因子p、2个质因子p,q。在图中的连接情况对应的是:(1,1)、(1,p)、(p,q),这样找到图中的最小环,环内点的数目即答案。因为环内每个点都出现了两次,这样就满足了完全平方数。
(1)自环(1,1),或者两个点被连接了多次,这些情况可以直接判断答案。
(2)否则就是对于两个点只被直接连接一次的图,枚举 1 ~ s q r t ( m a x ( a i ) ) 1~sqrt(max(a_i)) 1~sqrt(max(ai))为起点bfs求最小环。
注意:若分解为两个质因子p和q,那么 p ∗ q ≤ m a x ( a i ) p*q≤max(a_i) p∗q≤max(ai),即图中最大的质数为 s q r t ( m a x ( a i ) ) sqrt(max(a_i)) sqrt(max(ai)),只从 ≤ s q r t ( m a x ( a i ) ) ≤sqrt(max(a_i)) ≤sqrt(max(ai))的质数为起点就可以找到答案。
自测样例:
6
2 3 5 6 12 40
对应的图:

- ac代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+10;
int x, n, ans = INT_MAX;
struct node{
int nxt, eid;
};
vector<node> edges[maxn];
map<pair<int, int>, int> mp;
bool vis[maxn];
int dis[maxn];
queue<int> q;
void Div(int x, int id)
{
int p = 1, q = 1;
for(int i = 2; i*i <= x; i++)
{
if(x%i==0)
{
int num = 0;
while(x%i==0) num++, x/=i;
if(num%2)
{
if(p==1) p = i;
else q = i;
}
}
}
if(x!=1)
{
if(p==1) p = x;
else q = x;
}
if(p==1&&q==1)
{
ans = min(ans, 1);
return ;
}
mp[{p, q}]++;
if(mp[{p, q}]>=2)
{
ans = min(ans, 2);
return ;
}
edges[q].push_back({p, id});
edges[p].push_back({q, id});
}
int bfs(int s)
{
if(edges[s].empty()) return INT_MAX;
memset(vis, false, sizeof vis);//记录边是否访问过
memset(dis, 0, sizeof dis);
while(!q.empty()) q.pop();
q.push(s);
dis[s] = 1;//标记起始点已被访问
while(!q.empty())
{
int now = q.front(); q.pop();
for(int i = 0; i < edges[now].size(); i++)
{
int nxt = edges[now][i].nxt, eid = edges[now][i].eid;
if(vis[eid]) continue;//边不回返
if(dis[nxt]) return dis[now]+dis[nxt]-1;
vis[eid] = true;
q.push(nxt);
dis[nxt] = dis[now]+1;
}
}
return INT_MAX;//未成环
}
int main()
{
//freopen("/Users/zhangkanqi/Desktop/11.txt","r",stdin);
scanf("%d", &n);
for(int i = 1; i <= n; i++)
{
scanf("%d", &x);
Div(x, i);
}
if(ans!=INT_MAX) printf("%d\n", ans);
else
{
for(int i = 1; i <= 1000; i++) ans = min(ans, bfs(i));
if(ans==INT_MAX) ans = -1;
printf("%d\n", ans);
}
return 0;
}

探讨了如何通过分析数的质因数来确定其能否构成完全平方数的方法,利用图论中的最小环概念,结合BFS算法寻找满足条件的最小环,以此解决特定数学问题。

被折叠的 条评论
为什么被折叠?



