1. 程式人生 > 其它 >Codeforces 1325 E. Ehab‘s REAL Number Theory Problem —— 思維,bfs最小環,有丶東西

Codeforces 1325 E. Ehab‘s REAL Number Theory Problem —— 思維,bfs最小環,有丶東西

技術標籤:想法bfs2600

This way

題意:

問你最少選擇多少個數使得它們的笛卡爾積是完全平方數。每個數不會超過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; }