【数论】AGC003 Anticube

分析:

有点套路的数学题。

很显然,如果把每个数质因数分解,那么每个质因数的次数对3取模,归为一类,然后对每一类而言,考虑与其矛盾的类,取max即可。

重点就在于如何质因数分解。

很显然,如果要取模,则先保证质数的三次方在 1 0 10 10^{10} 1010以内,那么质数的范围就大大缩小,到了 [ 2 , 3 ∗ 1 0 3 ] [2,3*10^3] [2,3103]左右。这个范围内质数的个数就更少了,大约 340 340 340多个,那么可以直接把这一类质数筛掉,然后剩余的数只有三种可能: a i = p a_i=p ai=p a i = p 2 或 a i = p ∗ q ( p , q 为 互 不 相 同 的 质 数 ) a_i=p^2或a_i=p*q(p,q为互不相同的质数) ai=p2ai=pq(p,q),本质上1和3情况是一致的,所以只需要开个根号判断一下是不是2情况即可。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#define SF scanf
#define PF printf
#define MAXN 100010
#define MAXP 2300
using namespace std;
typedef long long ll;
int primes[MAXN],cnt;
int isprime[MAXP+100];
ll a[MAXN],les[MAXN],les1[MAXN];
map<ll,int> mp,st;
void prepare(){
	for(int i=2;i<=MAXP;i++){
		if(isprime[i]==0)
			primes[++cnt]=i;
		for(int j=1;i*primes[j]<=MAXP;j++){
			isprime[i*primes[j]]=1;
			if(i%primes[j]==0)
				break;	
		}
	}
}
int main(){
	prepare();
	//PF("%d",cnt);
	int n;
	SF("%d",&n);
	for(int i=1;i<=n;i++){
		SF("%lld",&a[i]);
		les1[i]=les[i]=a[i];
	}
	for(int i=1;i<=cnt;i++){
		ll p=primes[i];
		ll p2=p*p;
		ll p3=p*p*p;
		for(int j=1;j<=n;j++)
			if(a[j]%p==0){
				while(a[j]%p3==0){
					a[j]/=p3;
					les1[j]/=p3;
					les[j]/=p3;
				}
				if(les1[j]%p2==0){
					les1[j]/=p;
					les[j]/=p;
				}
				if(les[j]%p==0)
					les[j]/=p;
			}
	}
	for(int i=1;i<=n;i++){
		if(les[i]==1){
			les[i]=les1[i];
			continue;
		}
		ll x=(long long)sqrt(les[i]);
		if(x*x==les[i])
			les[i]=les1[i]/x;
		else
			les[i]=les1[i];	
	}	
	int ans=0;
	for(int i=1;i<=n;i++){
		if(a[i]==1){
			ans=1;
			continue;
		}
		mp[a[i]]++;
		st[a[i]]=les[i];
	}
	map<ll,int>::iterator it=mp.begin();
	for(;it!=mp.end();it++){
		ll x=it->first;
		int sum=it->second;
		ll y=st[x];
		ll xi=y*y/x*y;
		if(mp.count(xi)==0)
			ans+=sum;
		else{
			if(xi>x)
				ans+=max(sum,mp[xi]);	
		}
	}
	PF("%d",ans);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值