<think>题目要求:从1到n中选取尽可能多的整数,使得任意两个数互质。
注意:1和任何数互质,所以1可以随便选。但是题目已经包括1了。
观察:如果我们把所有的素数都选上,那么素数之间是互质的吗?是的,因为两个不同素数互质。
但是,这样还不够,因为还可以选1(1和任何素数都互质),以及一些合数(比如1和合数本身可能互质,但合数和合数之间不一定互质,合数和素数之间也可能互质)。
然而,题目要求任意两个数都要互质。因此,如果我们选了一个合数,那么它不能含有两个不同的素数因子吗?实际上,只要两个数没有公共的素因子即可。
但是,如果我们选了多个合数,它们可能共享同一个素因子。例如,4和6,它们有公因子2,所以不能同时选。
思路:我们可以将问题转化为独立集问题,但n最大为10^5,所以不能使用图论(复杂度太高)。
另一种思路:根据唯一分解定理,每个数可以分解为素因子的乘积。那么,如果两个数含有共同的素因子,那么它们就不互质。因此,如果我们限制每个素因子只能出现在一个数中,那么这些数就两两互质。
注意:1没有素因子,所以1可以和其他任意数共存。
但是,如何最大化数量?
我们可以这样想:因为每个数都可以分解成素因子,而每个素因子只能被一个数占用(即一个素因子只能出现在一个被选的数中)。那么,如果我们把所有的数按照其最小的素因子(或者任意一个素因子)分组,那么每组中我们只能选择一个数。但是,这样分组并不完全正确,因为一个数可能有多个素因子,它可以属于多个组。
然而,观察题目要求:任意两个数互质,即不能有公共素因子。所以,如果我们按照每个素数来考虑,那么每个素数最多只能被一个数使用(除非这个数只包含这个素数且其他数都不包含这个素数,但这样又可能冲突)。
实际上,这个问题有一个经典的解法:将所有的数按照其包含的最小素因子所在的组(即最小素因子)分组,但是同一个数只能属于一个组(以最小素因子为组号)。然后,在每一组中,我们最多只能选择一个数,因为一个组内的数有共同的最小素因子(除了1)。但是,注意:1没有最小素因子,所以1单独一组且可以选。
但是,这样分组后,如果我们每组选一个,那么整个集合就满足条件了吗?是的,因为不同组的数的最小素因子不同,而且如果两个数的最小素因子不同,它们可能还有其他的公因子吗?不一定,比如4和6:4的最小素因子是2,6的最小素因子也是2,所以它们在同一组,不能同时选。而4和9:4的最小素因子是2,9的最小素因子是3,不同组,但是4和9互质吗?是的,因为它们没有公共素因子。所以不同组的数不一定有公共素因子?实际上,由于我们只按最小素因子分组,而一个数可能还有其他素因子,但其他素因子可能在其他组。例如,6=2*3,它被分在2的组;15=3*5,它被分在3的组。那么6和15:6有因子3,15也有因子3,所以它们有公因子3,应该不能同时选。但是按照最小素因子分组,它们属于不同组(6在2组,15在3组),但实际它们不互质。所以这个分组方法不能保证不同组的数一定互质。
因此,我们必须保证:如果两个数有公共素因子(无论是不是最小),就不能同时选。所以我们需要避免任何公共素因子的出现。那么我们能否这样:对于每个素数p,所有包含p的数中最多只能选一个。那么整个问题就变成了:有若干个数(1到n),每个数被标记了它所包含的素数,然后我们要选一个集合,使得没有一个素数出现在两个数中。这就是一个匹配问题:每个素数只能被选一次,每个数相当于一个包含若干素因子的集合,我们要选最多的数使得每个素数至多在一个数中出现。
但是,这个问题是一个NP难问题(集合打包问题)?当n很大(10^5)时无法直接求解。
因此,我们需要寻找更高效的方法。
事实上,这个问题有一个基于贪心的经典解法:
1. 所有大于n/2的素数(即满足p>n/2且p是素数)只能单独出现。为什么?因为如果p>n/2,那么2p>n,所以p在1~n中只出现一次(即p本身)。而这样的素数,如果被选,那么它只能单独出现(因为它不能和任何其他倍数共存,但除了1,而1可以和它共存)。但是,如果我们选了一个这样的素数,那么其他任何包含p的数(实际上只有p自己)不会影响其他数吗?不会,因为p只有自己。然而,如果我们选了p,那么其他任何包含p的因子的数都不能选,但p的倍数只有p(因为2p>n),所以它只占用了p这个因子。因此,我们可以选它,并且它只占用了p这个因子。
2. 对于小于等于n/2的素数,它们的倍数可能有很多。如果我们选了一个合数,那么它可能会占用多个素数因子,从而阻止多个素数被选择。而如果我们选一个素数,那么它只占用一个素数因子(即它自己)。
因此,我们考虑:尽量选择小的素数,因为小的素数的倍数多,但是如果我们选择了小的素数,那么它的倍数就不能再选了。然而,我们也可以选择小的素数的一个倍数(比如一个合数)来替代这个素数,这样可能空出这个素数因子(但实际上合数会占用多个素数因子)。所以这并不简单。
实际上,有一个结论:在1~n中选取两两互质的最大集合,其大小等于1~n中每个素数p只能选一个数(即p的倍数)的情况下,能选的最大集合。而我们可以这样贪心:从大到小考虑每个数,如果这个数没有被任何已经选择的数排斥(即与已选集合的所有数都互质),我们就选它。但是判断互质需要和集合中每个数判断,复杂度高。
另一种思路:利用每个数的最小素因子。我们注意到:
任何大于1的数都可以写成若干个素数的乘积,其中最小素因子是唯一的。
那么,我们可以将2~n的数按照最小素因子分类。对于同一个最小素因子的所有数(即同一个组),我们只能从中选一个数(因为同一组的数有公共的最小素因子,所以它们之间不互质)。而1可以任意选。
因此,最大数量 = 1(选1) + 所有组中每组最多选一个数。
但是,这里有一个问题:同一个组内的数虽然最小素因子相同,但是它们可能还有其他素因子。如果我们选择一个数,那么它不仅占用了最小素因子,还占用了其他素因子。而其他素因子可能也是其他组的最小素因子,那么其他组就不能选包含这个素因子的数吗?注意,我们分组是按照最小素因子分的,一个数如果有多个素因子,它只属于它的最小素因子所在的组。因此,当我们从一组中选一个数时,这个数可能包含其他素因子(比如q),而q作为其他组的最小素因子,那么q所在组就不能选一个包含q的数吗?注意,q所在组中的数的最小素因子是q,而我们选的这个数虽然包含q,但它并不属于q组(因为它的最小素因子不是q,而是比q小的另一个素数)。所以q组中仍然可以选一个数,只要这个数不包含已经被选的其他素因子?这就不一定了。
例如:n=6。
分组:
最小素因子2:2,4,6
最小素因子3:3,6(但6的最小素因子是2,所以6在2组)
最小素因子5:5
注意:6的最小素因子是2,所以它在2组,而3组只有3。
如果我们从2组中选2,那么3组可以选3(因为2和3互质),5组选5,再加上1,总共4个(1,2,3,5)。
如果从2组中选4,那么4=2*2,它只包含因子2,所以它不会占用因子3和5,那么3组可以选3,5组选5,再加上1,也是4个(1,4,3,5)。
如果从2组中选6,那么6=2*3,它占用了2和3。那么3组就不能再选3了(因为6和3有公因子3)?但是3组中的3,它只包含因子3,而6已经包含了因子3,所以如果我们选了6,那么3组就不能再选3了。同时,由于6在2组,它已经代表了2组,所以2组也不能再选其他数。那么我们可以选:1,6,5,只有3个。所以不如选2或4。
因此,在每一组中,我们选择哪个数比较好?
我们的原则是:尽量选择不会占用太多其他素因子的数。也就是说,选择那些因子尽可能少的数。但因子少不一定好,比如4(因子2)和2(因子2),它们占用的其他素因子都是0(因为只有2),所以效果一样。而6(因子2和3)占用了两个素因子,导致3组不能选数。
结论:在同一个最小素因子的组内,我们选择这个组中数值最小的数?(即最小素因子本身)这样它就不会有其他素因子吗?不一定,比如最小素因子本身就是一个素数,它只有这一个素因子。而合数可能有多个素因子。所以选择素数(即最小素因子的那个素数)是最优的?因为这样它只占用一个素因子(自己),而不会占用其他素因子。
但是,在2组中,2(素数)和4(合数)都只占用了素因子2(4=2*2,只有2)。所以它们效果一样。而6=2*3,占用了2和3,所以效果差。因此在同一组内,我们选择只包含最小素因子(即不包含其他素因子)的数。如果存在这样的数,我们就选它(比如2组的2和4,它们都只包含素因子2,所以我们可以任意选一个,比如选2)。如果没有,我们就选一个包含其他素因子最少的数?但这样复杂度高。
然而,进一步思考:我们并不关心具体选哪个数,只要这个数占用的素因子尽可能少,且不会影响其他组。由于一个组内只能选一个数,那么我们可以选择占用其他素因子最少的数,也就是这个组中因子个数最少的数?但因子个数最少的不一定最好,因为我们希望占用的其他素因子(即不是最小素因子的那些)尽量少。那么,如果我们选择这个组中最小的数(即最小素因子本身):
这个数就是最小素因子p(素数),那么它只包含一个素因子p。这样,它就不会阻塞其他组(除了p组已经被选,但p组就是我们当前组,而且同一组我们只选一个,所以没关系)。而其他合数,比如p的倍数(如2p,3p等)不仅包含p,还包含其他素因子(比如2,3等),这样就会阻塞其他组(比如2组、3组)的数。
因此,在同一个组内,我们选择最小的数(即p)是最优的,因为它不会额外占用其他素因子。
但是,有没有可能不选p而选一个只包含p的幂的数(比如p^k)?这样的数只包含素因子p,不会占用其他素因子。所以选p^k和选p效果一样。那么我们可以选择任何一个只包含素因子p的数(即p的幂),因为这样的数不会阻塞其他组。而如果同一个组内没有只包含素因子p的数(也就是说,组内的数都是包含其他素因子的合数),那么我们就只能选一个包含其他素因子最少的数?但是这种情况在1~n中不会出现,因为p本身(即素数p)一定在组内,而且它只包含素因子p。所以每一组至少有一个数(即p)是只包含素因子p的。
因此,我们可以在每一组内直接选择这个最小素因子p(素数)作为代表。这样,每个组选一个数,所有组选的数之间不会因为其他素因子冲突吗?
假设有两个不同的素数p和q,我们选了p和q。因为p和q是不同的素数,所以它们互质。
另外,我们选的所有数都是素数(每个组的最小素因子,即素数),那么整个集合就是所有素数的集合,再加上1。那么最大个数就是1 + 素数个数。
但是,这个结论正确吗?例如n=6:
素数有:2,3,5 -> 3个素数,加上1一共4个。答案就是4。而样例n=6的输出是4,符合。
再看n=9:
素数有:2,3,5,7 -> 4个素数,加上1一共5个。样例输出5,符合。
但是,我们考虑n=1:只有1,那么最大个数就是1(选1)。按照我们的公式:1(1)+ 素数个数(0)=1,符合。
那么,是不是答案就是1 + [1,n]中素数的个数?
我们考虑n=4:
素数:2,3 -> 2个,加上1一共3个。
但是,我们是否可以选1,2,3,4?注意,2和4不互质(公因子2),所以不能同时选。按照我们的分组:
最小素因子2:2,4
最小素因子3:3
最小素因子?:1(单独考虑)
我们可以在2组选2(避免占用其他素因子),3组选3,1组选1,一共3个。也可以选4(4=2*2,只占用2)和3,再加上1,也是3个。所以最大数量为3。
但是,如果我们按照素数个数:1+2=3,正确。
然而,考虑n=10:
素数:2,3,5,7 -> 4个,加上1一共5个。
但是,我们还可以选1,4,9,5,7 -> 5个数:1,4,9,5,7。它们两两互质吗?
1和任何数互质。
4=2*2, 9=3*3, 5,7都是素数。
4和9:互质(没有公共因子)
4和5:互质
4和7:互质
9和5:互质
9和7:互质
5和7:互质
所以5个数可以。
同时,我们也可以选1,2,3,5,7 -> 5个数(素数方案),那么两种方案都是5个。
所以似乎素数方案已经是最优?因为5已经是最大值(无法再选6个数,因为1~10总共10个数,但互质的最大集合大小是多少?实际上,1,2,3,4,5,6,7,8,9,10中,任意两个相邻的自然数都不一定互质,而且有大量公因子2,3等)。
但如果我们选择合数4和9,我们仍然达到了5个。而素数方案也是5个。所以我们的结论还是1+素数个数=5。
所以,最大数量就是1+[1,n]中的素数个数?这个结论似乎成立。
但是,我们考虑n=8:
素数:2,3,5,7 -> 4个,加上1共5个。
但是,我们能不能选5个?我们选1,2,3,5,7 -> 5个数,但是2和8没有选?我们也可以选1,4,3,5,7(因为4=2*2,只占2,而3,5,7都是素数,互质;4和3,5,7都互质)。所以也是5个。
所以结论还是5。
但是,如果我们按照分组:在2组中,如果我们选4(4=2*2,只占2),那么其他组(3,5,7)都可以选自己的素数。因此,我们并不一定要选2组中的2,可以选4(只要4不会阻塞其他组,事实上也不会,因为4只包含2)。所以组内不一定选素数,可以选只包含最小素因子的幂的数。
那么,我们的结论是否还是:最大数量=1+所有最小素因子组的个数(即1~n中每个最小素因子对应一组,且每组选恰好一个数)?
注意,1~n中,除了1,每个数都有最小素因子,而且每个最小素因子p(p从2到n)对应一组。但是,组数等于素数个数吗?因为每个素数p作为最小素因子时,它对应一组。而合数的最小素因子一定是某个素数,并且这个素数小于等于合数本身。所以组的个数等于所有不超过n的素数的个数(因为每个素数p都对应一个组,而合数的组已经包含在某个素数的组里了)。所以组的个数就是不超过n的素数个数。
因此,最大数量=1+素数个数(即1加上不超过n的素数个数)。
那么,为什么n=6时答案是4(1+3个素数:2,3,5)?注意,素数个数是3(2,3,5),而1+3=4,符合。
但是,我们再看n=1:没有素数,1+0=1,正确。
所以,结论:最大选取数量 = 1 + (不超过n的素数个数)
然而,这个结论在n=4时:素数有2,3,所以1+2=3,正确。
那么,为什么我们之前的分组中,每个组选一个数(可以是这个素数,也可以是这个素数的幂,只要这个幂不会占用其他素因子)?注意,如果选一个素数的幂,那么它只占用这个素数,而不会占用其他素数,所以不会影响其他组。因此,我们可以在每个组中任意选一个数(只要它只包含这个最小素因子,即必须是这个素数的幂),但是如果我们选了一个包含其他素因子的数(比如6),那么它就会占用其他素因子,从而其他组就不能选包含那些素因子的数。所以为了最大化数量,我们应该避免选择包含其他素因子的数,而选择只包含最小素因子的数(即素数的幂)。而每个组至少有一个这样的数:即素数p本身(它是p^1)。
因此,方案:选1,然后在每个最小素因子组中选一个数(选素数p,或者选p的幂且这个幂不包含其他素因子)。而这样的数在组内一定存在(至少p本身)。因此,我们总能选1+素数个数个数。
但是,有反例吗?考虑n=12:
素数:2,3,5,7,11 -> 5个,加上1共6个。
那么最大数量就是6吗?我们看是否可行:
选1,以及2,3,5,7,11 -> 6个。
或者选1,4(2的幂),3,5,7,11 -> 6个,也是互质的。
所以6个是可行的。
但是,我们能不能选7个?不可能,因为素数最多5个,再加上1也只有6个。所以6个就是最大。
但是,如果我们不选素数而选合数呢?比如选1,4,9,5,7,11:
4=2^2, 9=3^2, 5,7,11都是素数 -> 这样也是6个,而且互质。
所以结论成立:最大数量就是1 + [1,n]中的素数个数。
因此,问题转化为:求1~n中素数的个数(然后加1)?注意:1不包括在素数中,但1单独算。
但是,注意:当n=1时,素数个数为0,加1为1,正确。
n=2时,素数有2(一个素数),那么1+1=2?但是1和2可以同时选吗?可以(互质)。所以答案2正确。
所以,算法:用筛法(埃氏筛或欧拉筛)求出1~n的素数个数,然后加1。
但是,我们再看题目:n=9,输出5;n=6,输出4。确实符合。
但是,为什么题目样例中n=9时可以选择1,5,7,8,9?这里8和9:8=2^3, 9=3^2,它们互质。所以这个集合也是5个元素。而我们的方案是1,2,3,5,7(素数方案)或者1,4,3,5,7(4代替2)等,都是5个。所以5个是正确的。
因此,我们得出结论:答案就是1 + [1,n]中的素数个数。
但是,注意:1~n中,1不是素数,所以素数个数就是不超过n的素数的个数。
因此,代码步骤:
1. 输入正整数n。
2. 如果n==1,则输出1。
3. 否则,计算1~n的素数个数cnt(注意:1不是素数,2是素数)。
4. 输出cnt+1。
但是,我们考虑一下效率:n最大10^5,用欧拉筛可以在O(n)内求出素数个数,也可以用埃氏筛(O(n log log n))。
然而,题目要求n最大10^5,所以用欧拉筛更好。
但是,我们再思考:有没有可能某个数被重复计数?没有,我们直接统计素数个数。
但是,我们之前的分组思想中,每个素数对应一个组,但是合数也会被分组(但合数组不影响,因为我们只关心素数个数,即组的个数)。所以答案就是1+素数个数。
因此,写代码:
步骤:
1. 创建一个大小的为n+1的bool数组is_prime,初始化全部为true(0和1位置标记为false)。
2. 用欧拉筛(线性筛)标记所有的非素数。
3. 统计is_prime中为true的个数(即素数个数)cnt。
4. 输出cnt+1。
但是,注意:1不是素数,所以n=1时,素数个数为0,然后0+1=1。
但是,我们考虑n=2:素数有2(1个),输出1+1=2。
因此,我们写一个欧拉筛。
然而,有没有可能不成立的情况?我们考虑n=10:素数个数为4(2,3,5,7),1+4=5,正确。
所以,代码如下:
注意:n最大10^5,欧拉筛可以过。
但是我们再验证一个:n=3:素数有2,3(2个),输出3(1+2=3)。但是1,2,3:三个数,任意两个互质(因为1和2互质,1和3互质,2和3互质)。所以正确。
因此,我们写欧拉筛。
但是,注意:欧拉筛需要两个数组:一个标记数组,一个素数数组(用来存放素数,以便后续用最小素因子筛)。
然而,我们只需要素数的个数,所以可以不用保存素数列表,但是为了效率,我们还是要用素数列表来筛。
代码结构:
int n;
cin >> n;
if (n == 1) {
cout << 1 << endl;
return 0;
}
// 注意:n>=2
vector<bool> is_prime(n+1, true); // 0-indexed, we use index 0..n, but 0 and 1 are not prime.
is_prime[0] = false;
is_prime[1] = false;
vector<int> primes; // 存放素数
for (int i = 2; i <= n; i++) {
if (is_prime[i]) {
primes.push_back(i);
}
for (int j = 0; j < primes.size() && i * primes[j] <= n; j++) {
is_prime[i * primes[j]] = false;
if (i % primes[j] == 0) {
break;
}
}
}
int cnt = primes.size(); // 因为primes中存放的就是所有素数
cout << cnt + 1 << endl;
但是,注意:我们也可以用计数的方式,在筛的时候计数。
但是,上面的筛法就是欧拉筛。
但是,我们考虑n=10^5时,欧拉筛的复杂度是O(n),可以接受。
因此,提交代码。
但是,我们还要考虑一种情况:当n=0?题目保证n>=1,所以无需考虑。
因此,我们写代码。
但是,我们再看分组的思想:组数等于素数个数,所以答案就是1+素数个数。因此这个结论正确。
所以,我们按照上述代码。
但是,我们运行一下样例:
输入6:素数有2,3,5 -> 3个,输出4,正确。
输入9:素数有2,3,5,7 -> 4个,输出5,正确。
因此,编写完整代码。
注意:欧拉筛中,我们只需要素数个数,所以也可以用一个计数器在遇到is_prime[i]为true时计数,而不需要primes数组?但是欧拉筛需要primes数组来筛合数。所以我们需要primes数组。
但是,当n很大(10^5)时,primes数组的大小约为10^4(因为10^5以内的素数个数不到10^4),所以可以。
我们可以用计数变量:
int cnt = 0;
for (int i=2; i<=n; i++) {
if (is_prime[i]) {
cnt++;
primes.push_back(i); // 注意,这里我们需要primes数组用于后续的筛,所以不能省略
}
...
}
最后输出cnt+1。
或者最后用primes.size()也可以。
我们选择用primes.size(),因为已经存了。
代码:
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n;
cin >> n;
// 当n=1时,素数个数为0,但此时不能进入欧拉筛循环(因为循环从2开始),所以单独处理。
if (n == 1) {
cout << 1 << endl;
return 0;
}
vector<bool> is_prime(n+1, true);
vector<int> primes;
is_prime[0] = false;
is_prime[1] = false;
for (int i = 2; i <= n; i++) {
if (is_prime[i]) {
primes.push_back(i);
}
for (int j = 0; j < primes.size(); j++) {
long long next = (long long)i * primes[j]; // 防止溢出
if (next > n) break;
is_prime[next] = false;
if (i % primes[j] == 0) {
break;
}
}
}
cout << primes.size() + 1 << endl;
return 0;
}
注意:当n比较大时,i*primes[j]可能会溢出int(因为n最大10^5,那么i最大10^5,primes[j]最大10^5,乘积最大10^10,而int最大约2e9,所以不会溢出?因为10^5*10^5=10^10,而10^10>2e9(2e9=2000000000),所以会溢出。因此,需要转成long long。
但是,我们可以提前判断:如果i*primes[j] > n,就break。
所以,我们在循环内:先计算next,如果next>n就break,否则标记。
这样,我们使用long long来避免溢出。
测试:n=100000,应该能过。
但是,如果n=100000,内层循环次数不会很多,因为每个合数只被筛一次。
因此,提交。
但是,我们考虑n=2的情况:i=2,然后primes[0]=2,next=4>2(n=2),所以break。然后primes.size()=1,输出2,正确。
所以,代码正确。
但是,我们也可以不用欧拉筛,用埃氏筛(因为10^5,埃氏筛也很快)。
埃氏筛代码:
is_prime[0] = false;
is_prime[1] = false;
for (int i = 2; i*i <= n; i++) { // 或者i<=sqrt(n)优化
if (is_prime[i]) {
for (int j = i*i; j <= n; j+=i) {
is_prime[j] = false;
}
}
}
// 然后统计素数个数:从2到n,is_prime[i]为true的个数cnt,然后输出cnt+1。
但是,埃氏筛的时间复杂度是O(n log log n),对于n=10^5,大约10^5*log(log(10^5)) ≈ 10^5 * log(12) ≈ 10^5 * 3.5,常数不大,所以也可以过。
两种方法都可以。
我们采用欧拉筛,因为更通用,而且当n更大时效率更高。
因此,最终代码(欧拉筛)如上。
但是,我们使用long long来避免溢出,因为i和primes[j]最大10^5,乘积最大10^10(大于2e9,所以int溢出)。所以必须用long long。
最后,注意:题目要求输出一个整数。
我们提交。
但是,我们考虑一个边界:n=100000时,素数个数是9592,然后加上1等于9593,输出即可。
所以,我们可以测试一下n=100000,看运行时间和结果是否正确。
实际运行:欧拉筛在n=100000时很快。
因此,最终代码:
</think>为了解决这个问题,我们需要从1到n中选取尽可能多的整数,使得任意两个数互质。最大数量可以通过计算1加上不超过n的素数个数来得到,因为1可以和任何数共存,而每个素数(或仅包含该素数的幂)不会与其他素数冲突。
### 解决方法
1. **问题分析**:选取的数必须两两互质。1与任何数互质,可以无条件选取。对于大于1的数,任意两个不同的素数互质,但合数可能与其他数有公因子。通过分组(按最小素因子分组),每组最多选一个数(该组中仅含最小素因子的幂,如素数本身),可以最大化数量。
2. **关键结论**:最大数量等于1(选取1)加上不超过n的素数个数。每个素数对应一个组,每组选一个数(如该素数本身),确保所有选取的数两两互质。
3. **算法选择**:使用欧拉筛(线性筛)高效计算1~n中的素数个数。欧拉筛时间复杂度为O(n),适合n最大为10^5的情况。
4. **优化**:使用`vector<bool>`标记素数,`vector<int>`存储素数列表,避免整数溢出使用`long long`计算乘积。
### 代码实现
```cpp
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n;
cin >> n;
if (n == 1) {
cout << 1 << endl;
return 0;
}
vector<bool> is_prime(n + 1, true);
vector<int> primes;
is_prime[0] = false;
is_prime[1] = false;
for (int i = 2; i <= n; i++) {
if (is_prime[i]) {
primes.push_back(i);
}
for (int j = 0; j < primes.size(); j++) {
long long next = (long long)i * primes[j];
if (next > n) break;
is_prime[next] = false;
if (i % primes[j] == 0) break;
}
}
cout << primes.size() + 1 << endl;
return 0;
}
```
### 解释
- **输入处理**:读取整数n,若n为1则直接输出1。
- **素数筛**:初始化`is_prime`数组,标记0和1为非素数。使用欧拉筛:
- 遍历2到n,若当前数i是素数,加入`primes`数组。
- 用当前素数`primes[j]`标记合数`i * primes[j]`,当`i`能被`primes[j]`整除时终止内层循环,确保每个合数只被标记一次。
- **输出结果**:素数个数为`primes.size()`,最大选取数量为素数个数加1(代表数字1)。
### 时间复杂度
- **欧拉筛**:时间复杂度为O(n),空间复杂度为O(n),高效处理n=10^5。
### 相关问题
1. 什么是欧拉筛?它如何确保每个合数只被标记一次?
2. 为什么在选取互质数时,1可以无条件选择?
3. 为什么每个最小素因子组只需选取一个数?
4. 如果允许选取多个合数,如何确保它们之间互质?