Codeforces 980D Perfect Groups 计数

原文链接https://www.cnblogs.com/zhouzhendong/p/9074164.html

题目传送门 - Codeforces 980D

题意

  $\rm Codeforces$ 真是个令人伤心的地方。

  伤心的 $zzd$ 现在给你一个含有 $n$ 个数字元素的数列。

  $zzd$ 问你对于 $1$ 到 $n$ 之间的每一个 $k$ 满足 $Q(序列)=k$ 的原序列的连续子序列个数。

  其中,$Q()$定义如下:

  把当前数列中的数分组,使得同组中任意两个数的乘积为完全平方数。其中最小分组数就是 $Q()$ 的值。

  $n\leq 5000,-10^8\leq a_i\leq 10^8$

题解

  伤心的 $zzd$ 再一次来到了令人伤心的 $\rm Codeforces $ ,再一次的看错题意,并再一次的没有考虑到坑点。

  很容易发现对于一个数,它的平方因子对最后的分组没有影响。

  我们把每一个数都除掉其最大平方因子,然后显然只有相同的数能分到同一组。

  于是离散化一下 $O(n^2)$ 统计即可。

  然后!!

  有一个特殊的数字叫做 "0" !

  $0$可以随便分组。

代码

#include <bits/stdc++.h>
using namespace std;
const int N=10005;
int n,a[N],cnt=0;
int pcnt=0,prime[N],f[N];
map <int,int> mp;
int tot,v[N],ans[N];
void get_prime(int n){
	for (int i=1;i<=n;i++)
		f[i]=1;
	f[1]=0;
	for (int i=2;i<=n;i++){
		if (!f[i])
			continue;
		prime[++pcnt]=i*i;
		for (int j=i*2;j<=n;j+=i)
			f[j]=0;
	}
}
int main(){
	get_prime(10000);
	scanf("%d",&n);
	mp.clear();
	for (int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		if (a[i]==0)
			continue;
		for (int j=1;j<=pcnt;j++)
			while (a[i]%prime[j]==0)
				a[i]/=prime[j];
		if (mp[a[i]]==0)
			mp[a[i]]=++cnt;
		a[i]=mp[a[i]];
	}
	for (int i=1;i<=n;i++){
		memset(v,0,sizeof v);
		tot=0;
		for (int j=i;j<=n;j++){
			if (a[j])
				tot+=v[a[j]]==0;
			v[a[j]]++;
			ans[max(tot,1)]++;
		}
	}
	for (int i=1;i<=n;i++)
		printf("%d ",ans[i]);
	return 0;
}

  

posted @ 2018-05-22 21:20  zzd233  阅读(342)  评论(1编辑  收藏  举报