【数论】【因数】D. Not Adding

137 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。


D. Not Adding【CF】【因数】

链接 : codeforces.com/problemset/…

一个数组,可以进行一个操作,对数组中的两个数ai,aja_i,a_jgcd(ai,aj)gcd(a_i,a_j)操作,结果如果不存在这个数组中,可以加在这个数组中。问最多进行多少次操作。

一个数组,可以进行一个操作,对数组中的两个数ai,aja_i,a_jgcd(ai,aj)gcd(a_i,a_j)操作,结果如果不存在这个数组中,可以加在这个数组中。问最多进行多少次操作。

明确:

  • 首先gcd的结果一定是小于等于做操作的两个数的,所以数组中数的大小一定小于数组中的最大值amaxa_{max}
  • ai,aja_i,a_j的最大公因数等于x,则ai,aja_i,a_j都是x的倍数。所以多个数做gcd结果为y,那么这些数都是y的倍数

做法:

  • cnt代表数组可以产生的最大长度

  • 使用cur[i]数组记录是i的倍数且在本数组中出现的所有数的gcd,只有在本数组出现才会被计算gcd

  • 枚举每个数,看它的倍数是否在数组中出现过,如果出现,进行gcd操作,最后枚举完i的所有倍数,cur[i]的结果就是本数组中所有i的倍数的数的gcd

  • 如果该gcd值等于i,那么i就可以被得到,cnt加一

  • 最后cnt-n即为结果

在平常的做题中关于因数的题目出现的次数还是非常多的,在做题过程中一定要尤其的重视!

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+5;

bool in[N];
int cur[N];

int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		int x;cin>>x;
		in[x] ++;
	}
	int tot = 0;
	for(int i=1;i<N;i++)
	{
		for(int j=i;j<N;j+=i)
			if(in[j])
				cur[i] = __gcd(cur[i],j);
		tot += (cur[i] == i);
	}
	cout<<tot - n << endl;
	return 0;
 }