C - Coprime 2(质因数)

C - Coprime 2https://vjudge.csgrandeur.cn/problem/AtCoder-abc215_d1.先把a数组元素里面每个元素的因数求出来,再把他们的倍数标记,剩下的1到M没标记的数就是答案

#include <iostream>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
using namespace std;

const int N  = 1e5 + 10;
int a[N];
bool st[N];
set<int> se;

void get_divisors(int x)//求约数
{
	//vector<int> res;
	for (int i = 1; i <= x / i; i ++ )
		if (x % i == 0)
	{
		se.insert(i);
		//res.push_back(i);
		if (i != x / i) se.insert(x/i);
			//res.push_back(x / i);
	}
	//sort(res.begin(), res.end());
	//return res;
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	memset(st,false,sizeof st);
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
	}
	for(int i=1;i<=n;i++)
	{
		get_divisors(a[i]);
	}
	
	for(auto i : se)
	{
		//cout<<i<<' ';
		if(i!=1)
			for(int j=i;j<=m;j+=i//约数的倍数
				st[j]=true;
	}
	vector<int> ans;
	for(int i=1;i<=m;i++)//没标记的选上
	{
		if(st[i]==false)
			ans.push_back(i);
	}
	
	cout<<ans.size()<<endl;
	for(int i=0;i<ans.size();i++)
		cout<<ans[i]<<endl;
	return 0;
}

2.根据算数基本定理,任何一个非质数的自然数都可以唯一分解为两个质数的乘积,而质数可以分解为1*它本身(质数),所以只需要把a数组里面的每个元素的质因数求出来,标记他们的倍数,然后遍历1到M

#include <iostream>
using namespace std;
const int N = 1e5 + 10;
bool st[N], vis[N];
int p[N], ans[N], d[N];
void divide(int x)//求质因子
{
     for (int i = 2; i <= x / i; i++)
        {
            if (x % i == 0)
            {
                st[i] = 1;
                while (x % i == 0)
                    x /= i;
            }
        }
        if (x > 1)
            st[x] = 1;
}
void get(int m)
{
     for (int i = 1; i <= m; i++)//标记质因子的倍数
    {
        for (int j = 2 * i; j <= m; j += i)//不知道为什么不超时,好像是调和级数,nlogn
        {
            if (st[i] == 1)
                st[j] = 1;
        }
    }
}
int main()
{
    ans[1] = 1;
    int n, m, cnt = 1, w = 0;
    scanf("%d %d", &n, &m);
 
    for (int i = 0; i < n; i++)
    {
        int x;
        cin >> x;
 
       divide(x);
    }
    get(m);
    for (int j = 2; j <= m; j++)
    {
        if (!st[j])
            ans[++cnt] = j;
    }
    printf("%d\n", cnt);
    for (int i = 1; i <= cnt; i++)
        printf("%d\n", ans[i]);
    return 0;
}

上面的双层循环等同于两个单层循环,不会超时 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值