Codeforces 1325 E. Ehab‘s REAL Number Theory Problem —— 思維,bfs最小環,有丶東西
阿新 • • 發佈:2020-12-22
題意:
問你最少選擇多少個數使得它們的笛卡爾積是完全平方數。每個數不會超過7個因子
題解:
每個數不會超過7個因子也就是說不會超過兩個質因子,當有3個質因子的時候,變會至少有
2
3
2^3
23種組合可能,與題意有悖。
那麼我們將每個數的奇數次質因子處理出來,分為以下三種情況:
1.有0個奇數次質因子,此時這個數就是完全平方數,直接輸出1
2.有2個奇數次質因子,此時將這兩個點連邊
3.有1個奇數次質因子,此時我們可以找一個非素數(我選擇1)連邊
最終只需要找最小環即可。使用bfs找最小環,首先將大小為2的環判掉,因為這個比較難搞,之後的話就記錄從哪裡轉移過來的,如果下一個點是這個點的話就continue掉即可。 但是此時會出現一種情況:
從這裡開始的時候,我們很難找到下面這個環。
但是我們又可以發現,兩個相連的數不會都大於1000,也就是說每個環裡面一定有至少一個1~1000的數。接下來我們列舉1~1000作為起點,然後做一遍即可。
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
const int inf=1e9;
#define ll long long
#define pa pair<int,int>
vector<int>son[N],vec;
int a[N];
int cnt,p[N], np[N],dis[N];
int hav[N],vis[N],ans=inf;
vector<int>used;
void bfs(int s){
queue<pa>Q;
Q.push({s,0});
vis[s]=1;
while(!Q.empty()){
int u=Q.front().first,fa=Q.front().second;Q.pop();
used.push_back(u);
for(int ne:son[u]){
if(ne==fa)continue ;
if(vis[ne]){
ans=min(ans,dis[ne]+dis[u]+1);
continue;
}
vis[ne]=1;
dis[ne]=dis[u]+1;
Q.push({ne,u});
}
}
}
map<pa,bool>mp;
int main()
{
for(ll i=2;i<N;i++){
if(!np[i]){
p[++cnt]=i;
for(ll j=i*i;j<N;j+=i)
np[j]=1;
}
}
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
int v=sqrt(a[i]);
if(a[i]==v*v||a[i]==(v+1)*(v+1)||a[i]==(v-1)*(v-1))return 0*printf("1\n");
int x=a[i];
for(int j=1;j<=cnt&&p[j]<=sqrt(x)+1;j++){
if(!np[x])
break;
int f=0;
while(x%p[j]==0)
x/=p[j],f^=1;
if(f)
vec.push_back(p[j]);
}
if(!np[x]&&x!=1)
vec.push_back(x);
if(vec.size()==0)return 0*printf("1\n");
else if(vec.size()==1){
if(hav[vec[0]]&1)
ans=min(ans,2);
hav[vec[0]]|=1;
hav[1]=2;
son[1].push_back(vec[0]),son[vec[0]].push_back(1);
}
else {
if(mp.count({vec[0],vec[1]}))ans=min(ans,2);
mp[{vec[0],vec[1]}]=mp[{vec[1],vec[0]}]=1;
son[vec[0]].push_back(vec[1]),son[vec[1]].push_back(vec[0]);
hav[vec[0]]|=2;
hav[vec[1]]|=2;
}
vec.clear();
}
for(int i=1;i<=1000;i++){
if(!(hav[i]&2))continue;
bfs(i);
for(int j:used)
vis[j]=dis[j]=0;
used.clear();
}
printf("%d\n",ans-inf?ans:-1);
return 0;
}