题意是给定一个集合 \(S\) 要求找到它的最大的子集使得子集里的任意两个数相乘都不是完全立方数。
\(S_i\le1e10\),集合大小小于 \(1e5\)。
首先对于每个数都把它的因子的指数对 \(3\) 取模,然后可以发现操作完了的形式都只有一种形式与它相乘可以得到完全立方数的数。那就在这两种数之间选一个贡献更大的。
正解做法不是很难理解但是难打。
我的做法较为无脑和暴力。
直接暴力先预处理出 \(1e5\) 以内的质数。然后对于每个数暴力质因数分解,计算对应的互斥的形式。然后用一个 \(unordered\_map\) 来计算贡献。
复杂度算不出来就是 \(O(能过)\)。
当时写的时候算了一下操作数不会超过 \(2e9\) 又看到5s时限就大胆开搞了。
其实要是没过我还会想想还能有啥trick的。但是都过来懒得管了/hsh。
view
#include<bits/stdc++.h>
#define re register
#define pii pair<int,int>
#define ios ios::sync_with_stdio(0),cin.tie(0)
#define fir first
#define sec second
#define il inline
#define ll long long
#define int ll
using namespace std;
const int inf=1e10;
int m,n,tot=2154,ans;
ll aqr[3001],a[100001],tmp,p[10001],ptot;
unordered_map<ll,int>mp;
unordered_map<ll,bool>vis;
bool P(int x){if(x<2)return 0;for(int i=2;i<=x/i;i++)if(!(x%i))return 0;return 1;
}
signed main(){ios;cin>>m;for(int i=2;i<=2154;i++)aqr[i]=i*i*i;for(int i=1;i<=m;i++){cin>>tmp;for(int j=2;j<=2154&&tmp>=aqr[j];j++)while(!(tmp%aqr[j]))tmp/=aqr[j];if(!mp[tmp])a[++n]=tmp;mp[tmp]++;}for(int i=2;i<=1e5;i++)if(P(i))p[++ptot]=i;//for(int i=1;i<=n;i++)cout<<a[i]<<' ';for(int i=1;i<=n;i++){ll s=a[i],cur=1ll;if(s==1||vis[s])continue;for(int j=1;j<=ptot;j++){int cnt=0;while(!(s%p[j]))cnt++,s/=p[j];if(!cnt)continue;if(cnt-1)cur*=p[j];else cur*=p[j]*p[j];}if(s!=1)cur*=s*s;if(mp[a[i]]>=mp[cur])ans+=mp[a[i]],vis[cur]=1;}cout<<ans+bool(mp[1]);return 0;
}