Live2D

Solution -「AGC 003D」「AT 2004」Anticube

Description

  Link.

  给定 n 个数 ai,要求从中选出最多的数,满足任意两个数之积都不是完全立方数。

  n105ai1010

Solution

  特判完全立方数——至多选一个。然后按一贯的套路约去立方因子。不过由于值域比较大,我们可以只筛出 max{ai}13 的素数,计算这些素数在 ai 的标准分解中的指数,借此求出 ai 和能与 ai 配成完全立方数的指数。而对于未被这些素数筛掉的部分,暴力判断是否是平方数就能计算出配对的数了。显然配对是相互的,所以用 std::map 做桶,在能配对的两个数中贪心地选取出现次数更多的数即可。

  复杂度 O(n(π(max{ai}13)+logn))

Code

#include <map>
#include <cmath>
#include <cstdio>
#include <iostream>

typedef long long LL;
#define int LL

const int MAXN = 1e5, MAXFAC = 2155;
const LL MAXV = 1e10;
int n, pn, pr[MAXFAC + 5], siz[MAXN + 5], rev[MAXN + 5];
LL val[MAXN + 5];
bool vis[MAXFAC + 5];
std::map<LL, int> buc;

inline LL rint () {
	LL x = 0; char s = getchar ();
	for ( ; s < '0' || '9' < s; s = getchar () );
	for ( ; '0' <= s && s <= '9'; s = getchar () ) x = x * 10 + ( s ^ '0' );
	return x;
}

inline void sieve ( const int n ) {
	for ( int i = 2; i <= n; ++ i ) {
		if ( ! vis[i] ) pr[++ pn] = i;
		for ( int j = 1; j <= pn && i * pr[j] <= n; ++ j ) {
			vis[i * pr[j]] = true;
			if ( ! ( i % pr[j] ) ) break;
		}
	}
}

inline bool issqr ( const LL x ) {
	LL t = pow ( x, 1.0 / 3 );
	return t * t * t == x || ( t + 1 ) * ( t + 1 ) * ( t + 1 ) == x;
}

signed main () {
	n = rint (), sieve ( MAXFAC );
	int ans = 0;
	for ( int i = 1; i <= n; ++ i ) {
		LL a = rint ();
		if ( issqr ( a ) ) { ans = 1; continue; }
		LL cur = 1, mtc = 1;
		for ( int j = 1; j <= pn && pr[j] <= a; ++ j ) {
			int cnt = 0;
			for ( ; ! ( a % pr[j] ); a /= pr[j], ++ cnt );
			if ( ! ( cnt %= 3 ) ) continue;
			cur *= pr[j], mtc *= pr[j];
			if ( cnt == 1 ) mtc *= pr[j];
			else cur *= pr[j];
			if ( mtc > MAXV ) mtc = 0;
		}
		LL sqt = sqrt ( a );
		cur *= a;
		if ( sqt * sqt == a || ( sqt + 1 ) * ( sqt + 1 ) == a ) mtc *= sqt;
		else {
			mtc *= a;
			if ( mtc > MAXV ) mtc = 0;
			mtc *= a;
		}
		if ( mtc > MAXV ) mtc = 0;
		if ( ! buc.count ( cur ) ) siz[buc[cur] = i] = 1, rev[i] = mtc;
		else ++ siz[buc[cur]];
		val[i] = cur;
	}
	for ( int i = 1; i <= n; ++ i ) {
		if ( ! siz[i] ) continue;
		if ( ! buc.count ( rev[i] ) ) {
			ans += siz[i], siz[i] = 0;
		} else {
			ans += std::max ( siz[i], siz[buc[rev[i]]] );
			siz[i] = siz[buc[rev[i]]] = 0;
		}
	}
	printf ( "%lld\n", ans );
	return 0;
}
posted @   Rainybunny  阅读(161)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示