[AGC003D] Anticube题解

传送门

简要题意:

\(n\) 个数,每个数为 \(a_i\),构造一个最大的集合 \(S\),要求 \(S\) 里面的数两两不为完全立方数,其中,

\[n \le 10^5,a_i \le 10^{10} \]

考虑将 \(a_i\) 分类

\(a_i=\coprod\limits_{i=1}^{k}p_i^{c_i}\),将 \(c_i\) 全都模 \(3\),得到 \(a_i\in \{\coprod\limits_{i=1}^{k}p_i^{c_i}(c_i<3)\}\),若我们选了 \(a_i\) 则我们不能选 \(a_j\in \{\coprod\limits_{i=1}^{k}p_i^{3-c_i}\}\)

容易发现,最优解就是在这两个集合中选大的那个集合,而这道题的答案就是这若干个大的集合加起来

因为\(a_i \le 10^{10}\),所以我们发现,制约我们的就是分解质因数以及储存,所以我们考虑对他进行分类讨论

首先明确 \(O(n \sqrt[3]{a})\) 是可以接受的

所以我们首先先将 \(c_i\) 全部模 \(3\),这个枚举质因数就好了,注意当质因数的三次方大于 \(a_i\) 时要退出。(时间复杂度 \(O(\sqrt[3]{a_i})\)

然后我们将 \(a_i\) 中小于等于 \(\sqrt[3]{a_i}\) 的质因数全部分解出来,然后对于分解后的剩下的数,这里可以确定的是,剩下的数最多是两个质数相乘(因为小于等于 \(\sqrt[3]{a_i}\) 的质数我们都分解了,剩下的必然大于 \(\sqrt[3]{a_i}\)),然后我们分类讨论(具体可以看代码):

\(1\)、剩下的数为 \(1\),我们已经分解完了,直接存入 \(map\)

\(2\)、剩下的数为两个相同质数相乘,也记录下来,存入 \(map\)

\(3\)、剩下的数为一个大质数或者为两个不同质数相乘,这时候我们考虑这个数是否小于等于 \(1e5\)

若小于等于 \(1e5\),记录下来,存入 \(map\)

若大于 \(1e5\),我们发现与这个数对立的另一个集合绝对为空,因为若要与这个数矛盾(即选了这个数不能选其他若干个数),则其他的数必然大于 \(1e10\),因为剩余的数可以表示为 \(p_i\)\(p_i\times p_j\),而与他矛盾的数至少是 \(p_i^2\)\(p_i^2\times p_j^2\),即剩余的数的平方。所以若这个数大于 \(1e5\),直接加入答案

考虑到 \(map\) 的时间复杂度和 \(map\) 的空间复杂度,这里的储存要用些小技巧,具体看代码。

上代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e5+50,T=1e5;
const ll M=1e10+50,INF=1e15;
int n;
ll a[N],b[N],c[N],f[N],ans,tzy,num;
bool prime[N];
int zs[N],idx,g;
map<ll,int> s[N][2];
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%lld",&a[i]);
	for(int i=2;i<=T;i++)
	{
		if(!prime[i]) zs[++idx]=i;
		if(i<=2160) g=idx;
		for(int j=1;j<=idx&&zs[j]*i<=T;j++)
		{
			prime[zs[j]*i]=true;
			if(i%zs[j]==0) break;
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=g;j++)
		{
			if(a[i]<zs[j]*zs[j]*zs[j]) break;
			while(a[i]%(zs[j]*zs[j]*zs[j])==0) a[i]=a[i]/zs[j]/zs[j]/zs[j];
		}
		int z=1,z2=1;
		if(a[i]==1)
		{
			ans=1;
			continue;
		}
		for(int j=1;j<=g;j++)
		{
			if(a[i]%zs[j]==0)
			{
				a[i]=a[i]/zs[j];
				z*=zs[j];
				if(a[i]%zs[j]==0)
				{
					a[i]=a[i]/zs[j];
					z*=zs[j];
					z2*=zs[j];
				}
				else z2*=zs[j]*zs[j];
			}
		}
		b[i]=z,c[i]=z2;
		tzy=sqrt(a[i]);
		if(tzy==1)
		{
			s[0][0][b[i]]++;
			if(!s[0][0][c[i]]&&s[0][0][b[i]]==1) f[i]=1;
		}
		else if(tzy*tzy==a[i])
		{
			s[tzy][1][b[i]]++;
			if(!s[tzy][0][c[i]]&&s[tzy][1][b[i]]==1) f[i]=1;
		}
		else if(a[i]<=T&&!prime[a[i]])
		{
			s[a[i]][0][b[i]]++;
			if(!s[a[i]][1][c[i]]&&s[a[i]][0][b[i]]==1) f[i]=1;
		}
		else num++;
	}
	ans+=num;
	for(int i=1;i<=n;i++)
	{
		if(f[i])
		{
			if(a[i]==1) ans=ans+max(s[0][0][b[i]],s[0][0][c[i]]);
			else if(a[i]<=T&&!prime[a[i]]) ans=ans+max(s[a[i]][0][b[i]],s[a[i]][1][c[i]]);
			else tzy=sqrt(a[i]),ans=ans+max(s[tzy][1][b[i]],s[tzy][0][c[i]]);
		}
	}
	printf("%lld\n",ans);
	return 0;
}
posted @ 2023-11-02 21:49  傻阙的缺  阅读(30)  评论(0)    收藏  举报