Perfect Groups
作者:互联网
教会了一个小的结论,假如有 \(A\times B=X^2,B\times C=Y^2\),那么\(A\times C=Z^2(X,Y,Z\in N^*)\)。用唯一分解定理啥的都可以证。
放到这道题中就是说几个元素可以暴力合并而不需要考虑集合内其他元素的感受,也就是说一个元素只要可以和集合内某个元素玩得来那么它就可以成为集合内的一个成员,无需验证和其它成员的关系。直接上并查集即可,由于数据范围提示 \(O(N^2)\) 做法,可以先做一次并查集记录每个元素所在的集合编号,然后枚举每个区间看这个区间内出现了多少个不同的编号,累加答案即可。特殊处理0,因为0可以加入到任何集合中,所以0不应该被算进来;但假如一个区间内全都是0,也是需要把0都分在一个集合内的,此时答案是1。
code
#include<bits/stdc++.h>
//#define feyn
#define int long long
const int N=5010;
using namespace std;
inline void read(int &wh){
wh=0;int f=1;char w=getchar();
while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
wh*=f;return;
}
inline int max(int s1,int s2){
return s1<s2?s2:s1;
}
int m,num,a[N],f[N],ans[N];
bool vis[N];
inline int find(int wh){
return f[wh]==wh?wh:f[wh]=find(f[wh]);
}
inline void merge(int x,int y){
f[find(y)]=find(x);
}
signed main(){
#ifdef feyn
freopen("in.txt","r",stdin);
#endif
read(m);
for(int i=1;i<=m;i++){
read(a[i]);f[i]=i;
for(int j=1;j<i;j++){
if(a[i]*a[j]>0){
int tmp=(int)sqrt(a[i]*a[j]);
if(tmp*tmp==a[i]*a[j])merge(i,j);
}
}
}
for(int i=1;i<=m;i++){
int an=0;memset(vis,false,sizeof(vis));
for(int j=i;j<=m;j++){
if(a[j]==0)ans[max(an,1)]++;
else{
int f=find(j);
if(vis[f]==false)an+=(vis[f]=true);
ans[an]++;
}
}
}
for(int i=1;i<=m;i++)printf("%I64d ",ans[i]);
return 0;
}
标签:Perfect,tmp,int,wh,Groups,集合,times,getchar 来源: https://www.cnblogs.com/dai-se-can-tian/p/16530977.html