牛客 - 牛牛的最大兴趣组(思维+数论)

Posted Frozen_Guardian

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了牛客 - 牛牛的最大兴趣组(思维+数论)相关的知识,希望对你有一定的参考价值。

题目链接:点击查看

题目大意:给出 n n n 个数,要求选出最多的数,使得任意两个数的乘积不能是三次平方数,三次平方数,诸如 2 3 = 8 , 3 3 = 27 2^3=8,3^3=27 23=8,33=27

题目分析:这个模型和前两天 c f cf cf 上遇到的一个样:CodeForces - 1497E2

这个模型的特点就是,假设要使得任意两个数的乘积不能是 m m m 次平方数的话,当我们将所有的数字中,出现次数为 m m m 的倍数的质因子都筛掉后,剩下的数一定会两两匹配。具体到某个质因子来说,假设其出现次数为 x x x,那么其需要和出现次数为 m − x m-x mx 的数字匹配,其乘积后该质因子的出现次数才能被 m m m 整除

下面就将本模型扩展到 m m m 次平方数来思考如何求解

又因为经过上述的处理后,除了 1 1 1 之外,其他的数都有且仅有唯一一个数字与其匹配。也就是对于每个数来说,只有一个数字与其乘积会不满足条件,所以这两个数字肯定不能同时出现。既然如此贪心去想的话,保留出现次数较多的那个数字显然是最优的

到此本题的思路就已经解决了,现在留下来两个难点需要我们逐个思考:

  1. 如何筛掉出现次数为 m m m 倍的质因子
  2. 在筛完的数字中,如何快速找到与其对应的那个数字,即满足两个数的乘积是 m m m 次平方数

针对第一点,最朴素的做法就是 O ( n ) O(\\sqrt{n}) O(n ) 的唯一分解定理了,对于出现次数可以被 m m m 整除的质因子直接舍弃即可,可惜时间复杂度不允许

然后考虑也比较常用的,预处理出每个数字的最小质因子,然后 O ( l o g n ) O(logn) O(logn) 去筛质因子,这种实现时间复杂度可行,但是我们无法预处理到 2 e 9 2e9 2e9 的数据范围

其实我们不难发现,并不需要枚举出所有的质因子然后判断,我们的目标是为了筛掉所有 m m m 次平方数的数字,换句话说我们可以预处理出 m m m 次平方的数字,然后用这些数字去筛即可,而这样的 m m m 次平方数,最多有 2 e 9 m \\sqrt[m]{2e9} m2e9 个数字,又因为合数总是可以被分解成质数,所以我们只需要保留质因子即可,这样有效数字最终约等于 2 e 9 m l o g m \\frac{\\sqrt[m]{2e9}}{logm} logmm2e9 ,针对本题而言,当 m = 3 m=3 m=3 的时候,这个数值约等于 200 200 200

那么还剩下一个问题,如何找到对应的数字呢,实际上最朴素的做法还是 O ( n ) O(\\sqrt{n}) O(n ) 去唯一分解这个数,如果对于某个质因子 p p p,其出现次数是 x x x,那么其对应的那个数字, p p p 的出现次数一定是 m − x m-x mx

到此为止,网上的部分题解,都是 O ( n n ) O(n\\sqrt{n}) O(nn ) 实现的,因为本题数据水了,所以给放过去了,其实一组很简单的 h a c k hack hack 样例就是, n n n 1 e 9 + 7 1e9+7 1e9+7,直接就把复杂度卡成至少 1 e 5 ∗ 1 e 4 = 1 e 9 1e5*1e4=1e9 1e51e4=1e9 起步了

所以该如何去查找对应的那个数字呢,假设我们要找 x x x 对应的数字,只需要将 x x x 变成 x m − 1 x^{m-1} xm1,然后再将出现次数为 m m m 的质因子筛掉即可,具体原理就是:对于任意两个相邻的自然数来说,都是互质的,所以 g c d ( m − 1 , m ) = 1 gcd(m-1,m)=1 gcd(m1,m)=1,对于公式 a + a ∗ ( m − 1 ) = a ∗ m a+a*(m-1)=a*m a+a(m1)=am,两边同时对 m m m 取模得到 a + a ∗ ( m − 1 ) = 0 ∣ m a+a*(m-1)=0|m a+a(m1)=0m,所以将 x x x 变为 x m − 1 x^{m-1} xm1 然后再将出现次数为 m m m 的倍数的质因子筛掉就可以找到对应的数字了

总的时间复杂度就是 O ( n 2 e 9 m ) O(n\\sqrt[m]{2e9}) O(nm2e9 ),对于本题而言就是 O ( 200 ∗ n ) O(200*n) O(200n),实现的时候我套了个 m a p map map ,理论上说应该是不可以的,但因为本题数据水,所以是可以过的,如果是正解的话我感觉需要打个哈希降一下复杂度,大概就是 unordered_map 了

代码:

// Problem: 牛牛的最大兴趣组
// Contest: NowCoder
// URL: https://ac.nowcoder.com/acm/contest/7604/C
// Memory Limit: 524288 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// #pragma GCC optimize(2)
// #pragma GCC optimize("Ofast","inline","-ffast-math")
// #pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
#define lowbit(x) x&-x
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
template<typename T>
inline void read(T &x)
{
    T f=1;x=0;
    char ch=getchar();
    while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
    x*=f;
}
template<typename T>
inline void write(T x)
{
    if(x<0){x=~(x-1);putchar('-');}
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
const int inf=0x3f3f3f3f;
const int N=1e6+100;
bool vis[N];
vector<int>pri;
map<LL,int>mp;
void init() {
	for(int i=2;i<=2000;i++) {
		if(vis[i]) {
			continue;
		}
		for(int j=i+i;j<=2000;j+=i) {
			vis[j]=true;
		}
	}
	for(int i=2;1LL*i*i*i<=2e9;i++) {
		if(!vis[i]) {
			pri.push_back(i*i*i);
		}
	}
}
LL change(LL x) {
	for(auto it:pri) {
		while(x%it==0) {
			x/=it;
		}
	}
	return x;
}
int main()
{
#ifndef ONLINE_JUDGE
//	freopen("data.in.txt","r",stdin);
//	freopen("data.out.txt","w",stdout);
#endif
//	ios::sync_with_stdio(false);
	init();
	int n;
	read(n);
	for(int i=1;i<=n;i++) {
		LL x;
		read(x);
		mp[change(x)]++;
	}
	int ans=0;
	for(auto &it:mp) {
		if(it.first==1) {
			ans++;
			continue;
		}
		LL rk=change(it.first*it.first);
		if(!mp.count(rk)) {
			ans+=it.second;
		} else {
			ans+=max(it.second,mp[rk]);
			it.second=mp[rk]=0;
		}
	}
	cout<<ans<<endl;
    return 0;
}

以上是关于牛客 - 牛牛的最大兴趣组(思维+数论)的主要内容,如果未能解决你的问题,请参考以下文章

牛牛做数论(素数+思维)

2020牛客寒假算法基础集训营3——E.牛牛的随机数数位DP(待补)

2020牛客寒假算法基础集训营3——I.牛牛的汉诺塔记忆化

[牛客网] 拼凑三角形

[牛客网] 拼凑三角形

2022牛客寒假算法基础集训营1全部题解