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;
}
上面的双层循环等同于两个单层循环,不会超时