[AGC003D] Anticube题解
简要题意:
有 \(n\) 个数,每个数为 \(a_i\),构造一个最大的集合 \(S\),要求 \(S\) 里面的数两两不为完全立方数,其中,
考虑将 \(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;
}

浙公网安备 33010602011771号