[CF1325E] Ehab's REAL Number Theory Problem
Ehab's REAL Number Theory Problem
题目描述
You are given an array of length that has a special condition: every element in this array has at most 7 divisors. Find the length of the shortest non-empty subsequence of this array product of whose elements is a perfect square.
A sequence is a subsequence of an array if can be obtained from by deletion of several (possibly, zero or all) elements.
输入格式
The first line contains an integer ( ) — the length of .
The second line contains integers , , , ( ) — the elements of the array .
输出格式
Output the length of the shortest non-empty subsequence of product of whose elements is a perfect square. If there are several shortest subsequences, you can find any of them. If there's no such subsequence, print "-1".
样例 #1
样例输入 #1
3
1 4 6
样例输出 #1
1
样例 #2
样例输入 #2
4
2 3 6 6
样例输出 #2
2
样例 #3
样例输入 #3
3
6 15 10
样例输出 #3
3
样例 #4
样例输入 #4
4
2 3 5 7
样例输出 #4
-1
提示
In the first sample, you can choose a subsequence .
In the second sample, you can choose a subsequence .
In the third sample, you can choose a subsequence .
In the fourth sample, there is no such subsequence.
至多7个因子是什么条件?仔细分析,其实是说明这个数至多有两个不同质因数。
要求一个序列的所有数相乘为完全平方。也就代表任意一个质因数的次数之和为偶数。那么在某一个数中,如果有一个质因数出现了偶数次,那他很没用,出现了和没出现一个样,我们就可以不理他。然后现在要求选出来的序列每种质因数出现偶数次,会想到一件事。如果有一个数的质因数是 ,那么就一定需要一个含有 的数和一个含有 的数,然后往后又要推。最后一定是一个环。所以考虑最小环构图。
构图很简单,如果存在一个数 ( 为质数),那么就可以从 向 连一条无向边。如果一个数次数为奇数的质因数只有一个,那就把质因数 和 连边。
现在到了跑最小环。最小环问题解法可以使用 Floyd,但是这里完全行不通。注意到这里的边是无权的,对于最小环,有一种 的算法。钦定一个一定在最小环上的点 ,用它跑出一棵 bfs 树。然后对于一条不在树上的边 ,设点 到点 的最短路为 ,那么如果点 和点 要同时在最小环上,最小环长为 。
或许有人会问,如果点 在 bfs 树上的 lca 不为点 ,怎么办?其实没关系,因为等我枚举 枚举到他们的 lca 时,自然就会把那个环算入了。
的复杂度仍然不能接受,但发现不存在两个数 ,同时又有连边。这说明,最小环上一定有一个点 。所以我们枚举在环上的点时只用枚举小于等于1000的质数就行了。
复杂度
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5,M=1e6+5;
int n,a[N],pri[M],hd[M],dp[M],q[M],l,r,ans=2000000000,e_num(1),pw[M];
vector<int>g[M];
struct edge{
int v,nxt,f;
}e[N<<1];
void add_edge(int u,int v)
{
e[++e_num]=(edge){v,hd[u]};
hd[u]=e_num;
}
void run(int x)
{
memset(dp,0,sizeof(dp));
dp[q[l=r=1]=x]=1;
for(int i=2;i<=e_num;i++)
e[i].f=0;
while(l<=r)
{
int k=q[l];
++l;
for(int i=hd[k];i;i=e[i].nxt)
{
if(!dp[e[i].v])
{
e[i^1].f=1;
dp[e[i].v]=dp[k]+1;
q[++r]=e[i].v;
}
else if(!e[i].f)
{
// printf("%d %d %d\n",x,k,e[i].v);
ans=min(ans,dp[k]+dp[e[i].v]-1);
}
}
}
}
int main()
{
for(int i=2;i<M;i++)
{
// printf("%d\n",i);
if(!pri[i])
{
for(int j=1;j*i<M;j++)
{
pri[j*i]=1;
if(j%i==0)
pw[j]=pw[j/i]^1;
if(!pw[j])
g[j*i].push_back(i);
}
for(int j=1;j*i<M;j++)
pw[j]=0;
}
}
// puts("hjhakioi");
// for(int i=1;i<M;i++)
// {
// printf("%d\n",i);
// for(int j=0;j<g[i].size();j++)
// printf("%d ",g[i][j]);
// putchar('\n');
// }
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",a+i);
if(g[a[i]].size()==1)
{
add_edge(1,g[a[i]][0]);
add_edge(g[a[i]][0],1);
}
else if(g[a[i]].size())
{
add_edge(g[a[i]][0],g[a[i]][1]);
add_edge(g[a[i]][1],g[a[i]][0]);
}
else
{
printf("1");
return 0;
}
}
for(int i=1;i<=1000;i++)
run(i);
if(ans>n)
printf("-1");
else
printf("%d",ans);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现