E. Ehab's REAL Number Theory Problem
time limit per test
3 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
You are given an array aa of length nn 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 aa is a subsequence of an array bb if aa can be obtained from bb by deletion of several (possibly, zero or all) elements.
Input
The first line contains an integer nn (1≤n≤1051≤n≤105) — the length of aa.
The second line contains nn integers a1a1, a2a2, ……, anan (1≤ai≤1061≤ai≤106) — the elements of the array aa.
Output
Output the length of the shortest non-empty subsequence of aa 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".
Examples
input
Copy
3
1 4 6
output
Copy
1
input
Copy
4
2 3 6 6
output
Copy
2
input
Copy
3
6 15 10
output
Copy
3
input
Copy
4
2 3 5 7
output
Copy
-1
Note
In the first sample, you can choose a subsequence [1][1].
In the second sample, you can choose a subsequence [6,6][6,6].
In the third sample, you can choose a subsequence [6,15,10][6,15,10].
In the fourth sample, there is no such subsequence.
题意:给你n(n<=1e5)个数a[i](<=1e6),保证每个数有不超过7个因子,求最少选出多少个数,它们的乘积是完全平方数。
思路:
每个数不超过7个因子,那么它的素因子最多只有两个(三个的话就有8个因子了),设为x和y
那么我们要使x,y的幂次变为偶数。有以下几种情况:
①这个数本身就是完全平方数,直接特判
②这个数含有一个幂次为奇数的质因子x,建立边(1,hash[x]) (由于质因子最大可达六位数,所以进行离散化处理)
③这个数含有两个幂次为奇数的质因子x,y,建立边(hash[x],hash[y])
这样,我们只要从建立的图里找到一个长度最小的环,就是答案。(因为环中所有结点的度为偶数,想想是不是)
但是直接枚举每个点是O(n*n)的。考虑环中一定有数值小于1000的点,因此我们枚举数值1000以下所有结点,从这些结点出发找最小环。
注意,找环的时候,不能用dfs(否则会wa在149组,dfs确实不能找出所有的环),要用bfs(类似于最短路思想)
代码:
#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
#define dep(i,a,b) for(register int i=(a);i>=(b);i--)
using namespace std;
const int maxn=1e6+5;
//const double pi=acos(-1.0);
//const double eps=1e-9;
//const ll mo=1e9+7;
int fa[maxn],dp[maxn];
int n,m,k,cnt,ans;
vector<int>vv[maxn],vc[maxn];
map<int,int>hs,mp;
map<pair<int,int>,int>mm;
void dfs(int u,int f){// 注意,dfs不对!!!!!!!!
dp[u]=dp[f]+1;
for(int i=0;i<vc[u].size();i++){
int v=vc[u][i];
if(v==f) continue;
//cout<<u<<" "<<v<<" & "<<dp[u]<<" "<<dp[v]<<endl;
if(dp[v]){
ans=min(ans,max(dp[u],dp[v])-min(dp[u],dp[v])+1);
}
else dfs(v,u);
}
}
int main(){
scanf("%d",&n);
ans=inf;
rep(i,1,n){
int x,ok=1;
scanf("%d",&x);
for(int j=2;j*j<=x;j++) if(x%j==0){
int cnt=1;x/=j;
while(x%j==0) {x/=j;cnt^=1;}
if(cnt) {vv[i].push_back(j);ok=0;}
}
if(x>1) vv[i].push_back(x);
if(ok&&x==1) {ans=1;}
}
if(ans==1) {puts("1");return 0;}
hs[1]=1;cnt=1;
rep(i,1,n){
if(vv[i].size()==1){
if(mp[vv[i][0]]) {ans=2;break;}
mp[vv[i][0]]=1;
if(!hs[vv[i][0]]) hs[vv[i][0]]=++cnt;
vc[1].push_back(hs[vv[i][0]]);
vc[hs[vv[i][0]]].push_back(1);
}
if(vv[i].size()==2){
int u=vv[i][0],v=vv[i][1];
if(u>v) swap(u,v);
pair<int,int> p=make_pair(u,v);
if(mm[p]) {ans=2;break;}
mm[p]=1;
if(!hs[u]) hs[u]=++cnt;
if(!hs[v]) hs[v]=++cnt;
vc[hs[u]].push_back(hs[v]);
vc[hs[v]].push_back(hs[u]);
}
}
/*rep(i,1,cnt) if(vc[i].size()){
for(int j=0;j<vc[i].size();j++)
cout<<vc[i][j]<<" ";
cout<<endl;
}*/
if(ans==2) {puts("2");return 0;}
queue<int>q;
for(int i=1;i<=1000;i++) if(hs[i]){
while(!q.empty()) q.pop();
rep(j,0,cnt) {fa[j]=0;dp[j]=inf;}
q.push(hs[i]);fa[hs[i]]=1;dp[hs[i]]=1;
while(!q.empty()){
int u=q.front();q.pop();
for(int j=0;j<vc[u].size();j++){
int v=vc[u][j];
if(fa[u]==v) continue;
//cout<<u<<" "<<v<<" * "<<dp[u]<<" "<<dp[v]<<endl;
if(dp[v]!=inf) ans=min(ans,dp[u]+dp[v]-1);
if(dp[v]>dp[u]+1){
dp[v]=dp[u]+1;
if(!fa[v]) {
fa[v]=u;
q.push(v);
}
}
}
}
}
//cout<<"***"<<endl;
if(ans==inf) puts("-1");
else printf("%d\n",ans);
return 0;
}