cunzai_zsy0531

关注我

AT2004 [AGC003D]Anticube 题解

题面

由于乘起来不能是完全立方数,考虑对每个数质因数分解之后,所有的指数都 \(\bmod 3\),这样操作完之后,每个数都与唯一一个数对应(乘起来是完全平方数),即对于每个质因子,如果次数为 \(1\),对应的那个数的次数应该为 \(2\),反之同理。这样可以建立起一个一一映射,对于每个映射都只能选择一种数,另一种数不能选。

由于 \(v\leq 10^{10}\),直接质因数分解显然是不行的。考虑如果一个质因子 \(p>\sqrt[3]{v}\),那么他最多只有 \(2\) 次。考虑先把 \(p\leq \sqrt[3]{v}\) 的质数全筛出来,剩下的那个数只可能是 \(1,p,p^2,pq(p,q\in Prime)\) 中的一种。\(1\) 不需要考虑,如果是 \(p^2\) 应该映射到 \(p\)\(p\)\(pq\) 都应映射到他们的平方,所以只需要判断这个数是不是完全平方数就可以了。注意在映射的过程中,一旦超过 \(10^{10}\) 立即停止就行了。

还需要注意,\(1\) 是映射到自己的,这个数自始至终只能出现 \(1\) 次。

点击查看代码
const int N=2e5+13;
int n,m,prm[N];
ll Lim=1e10;
std::unordered_map<ll,int> tong;
int main(){
//file();
	Math::Onshai(prm,m,3000);tong.clear();
	read(n);
	int cnt=0;bool fflag=0;
	for(int i=1;i<=n;++i){
		ll x;read(x);ll t=1;__int128 y=1;bool ok=1;
		for(int j=1;j<=m;++j){
			if(x%prm[j]==0){
				int c=0;
				while(x%prm[j]==0) x/=prm[j],++c;
				c%=3;
				if(c==1) t*=prm[j];
				else if(c==2) t*=prm[j]*prm[j];
			}
			if(x==1) break;
		}
		if(x!=1) t*=x;
		if(t==1&&fflag) continue;
		else if(t==1) fflag=1;
		if(tong[t]){--tong[t];continue;}
		for(int j=1;j<=m;++j){
			if(t%prm[j]==0){
				int c=0;
				while(t%prm[j]==0) t/=prm[j],++c;
				c%=3;
				if(c==1) y*=prm[j]*prm[j];
				else if(c==2) y*=prm[j];
			}
			if(y>Lim){ok=0;++cnt;break;}
			if(t==1) break;
		}
		if(!ok) continue;
		if(t!=1){
			ll tmp=sqrt(t);
			if(tmp*tmp==t) y*=tmp;
			else y*=(__int128)t*t;
			if(y>Lim) ok=0,++cnt;
		}
		if(!ok) continue;
		ll yy=y;
		++tong[yy],++cnt;
	}
	println(cnt);
	return 0;
}
posted @ 2022-05-20 12:05  cunzai_zsy0531  阅读(30)  评论(0编辑  收藏  举报