专栏文章
题解:P14073 [GESP202509 五级] 数字选取
P14073题解参与者 3已保存评论 5
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 5 条
- 当前快照
- 1 份
- 快照标识符
- @minqwsj7
- 此快照首次捕获于
- 2025/12/02 06:53 3 个月前
- 此快照最后确认于
- 2025/12/02 06:53 3 个月前
题解:P14073 [GESP202509 五级] 数字选取
我这周末刚去考的五级,所以下来就把在考场上的思路顺了一下写的,考场上的思路可能有点笨,但是可以 AC。
思路:
题意:
这里题面描述的题意已经很清楚了,就是从 到 中选若干个互质的数,要选的数的数量最大。
我的方法:
用两个数组 和 , 用于存储要选的数, 用于判断这个数能不能选。
数组的细致作用:
-
一开始先把 里面所有数标记成 ,表示可以取( 就代表不可取)。
-
假如我选了 这个数,为了保证 数组中的数互质,就不能选 的倍数,那这个时候就用一个 for 循环把 的倍数都标记成 ,表示不可取,之后判断选不选那个数的时候就看看 的值是否为 。
细致:
首先 肯定要选,然后看 和 , 和 如果都选的话,那 数组中很多值都会被标记成 ,不值得,所以分别考虑选 和选 。
拿选 来举例子:
-
选 和 ,那就是:。
-
用 for 循环遍历把 标记为 :
for(int i=2;i<=n;i+=2) b[i]=1;。 -
从 开始便利,看是否与前一个数互质且 ,如果是的话就把这个数插入到 数组中,同时把 标记成 ,同时
ans++。 -
最后再输出
ans就好了。
Code:
CPP#include<bits/stdc++.h>
using namespace std;
#define int long long
int gcd(int a,int b){
return b==0?:gcd(b,a%b);
}
int a[100100],b[100100];//a=>选的数 b=>是否可选
int ans=0;
signed main(){
int n;cin>>n;
a[1]=1;
//选2
a[2]=2;
int k=2;//a中数的个数,插入新数时数的下标
for(int i=2;i<=n;i+=2) b[i]=1;
for(int i=3;i<=n;i++){
if(gcd(i,a[k])==1&&b[i]==0){
for(int j=i;j<=n;j+=i) b[j]=1;//选了这个数后把这个数的倍数都标记为 1
ans++;
k++;
a[k]=i;
}
}
int ans1=ans+2;//一开始的 a[1] 和 a[2] 也要算进去
//清空上一个状态
sizeof(a,0,sizeof a);
sizeof(b,0,sizeof b);
a[1]=1;
k=2;
ans=0;
//选3
a[2]=3;
for(int i=3;i<=n;i+=3) b[i]=1;
for(int i=4;i<=n;i++){
if(gcd(i,a[k])==1&&b[i]==0){
for(int j=i;j<=n;j+=i) b[j]=1;
ans++;
k++;
a[k]=i;
}
}
int ans2=ans+2;
cout<<max(ans1,ans2);
return 0;
}
由于这个思路是我在考场上想到的,所以可能有点麻烦,如果有可以改进的地方希望提出。
相关推荐
评论
共 5 条评论,欢迎与作者交流。
正在加载评论...