2018.10.31【校内模拟】一串数字(唯一分解)(贪心)

传送门


解析:

其实很容易想到分解质因数,然后次数%3\%3后合并计算出它的特征数,同时计算出不能与它共同选择的数的特征数。

显然特征数相同的数可以合并。然后两个中贪心就是了。

注意所有本来就是立方数的数当中,我们直接选择价值最大的那个。


代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const

inline int getint(){
	re int num;
	re char c;
	while(!isdigit(c=gc()));num=c^48;
	while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
	return num;
}

cs int N=100005;
cs int P=100005;

int prime[P],pcnt;
bool mark[P];
inline void linear_sieves(int len=P-5){
	for(int re i=2;i<=len;++i){
		if(!mark[i])prime[++pcnt]=i;
		for(int re j=1;j<=pcnt&&i*prime[j]<=len;++j){
			mark[i*prime[j]]=true;
			if(!(i%prime[j]))break;
		}
	}
}

inline pair<ll,ll> factor(int x){
	ll ori=1,rev=1;
	for(int re i=1;i<=pcnt&&prime[i]<=x;++i){
		int cnt=0;
		while(x==x/prime[i]*prime[i])x/=prime[i],++cnt;
		cnt%=3;
		if(cnt)(cnt==2)?(ori*=1ll*prime[i]*prime[i],rev*=prime[i]):(rev*=1ll*prime[i]*prime[i],ori*=prime[i]);
	}
	return make_pair(ori,rev);
}

ll cost[N],revcost[N]; 
int n;
ll ans;
signed main(){
	linear_sieves();
	n=getint();
	for(int re i=1;i<=n;++i){
		int x=getint(),val=getint();
		pair<ll,ll> sieve=factor(x);
		if(sieve.first==1){
			ans=max(ans,1ll*val);
			continue;
		}
		else (sieve.first>sieve.second?revcost[sieve.second]:cost[sieve.first])+=val;
	}
	for(int re i=2;i<N;++i)ans+=max(cost[i],revcost[i]);
	cout<<ans;
	return 0;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章