题目链接
题意:
给出一个\(N(3≤N≤20000)\)构造一个长度为\(N\)的序列,使得其中每个数\(a_i\),\(1≤ai≤30000\),\(gcd(a_1,a_2,a_3...a_n)=1\),\(gcd(a_i,\sum^n_{j=1,j≠i}a_j)≠1\),所有数不重复
思路:
特判一下n=3 .
考虑两个集合,第一个集合 A 代表<=30000的所有偶数,显然 |A| = 15000;
第二个集合 B 代表 <=30000的所有非偶数的3的倍数,显然 |B| = 5000。
神奇的发现 |A| + |B| = n可以取的最大值,那么这种方案能否构造成功呢?
设 i 为在B中取的元素个数, j 为在A中取的元素的个数,那么i和j需要满足(假设我们在每个集合都是从小到大取):
- i+j = n;
- i<=5000 && i是偶数;
- j<=15000 && j%3不等于1;
void solve()
{
scanf("%lld",&n);
if(n==3){
puts("2 5 63");
return ;
}else {
for(int i=2;i<n;i+=2){
if((n-i)<=15000&&i<=5000&&(n-i)%3!=1){
for(int j=2,c=1;j<=30000&&c+i<=n;j+=2,c++) {
printf("%d ",j);
}
for(int j=3,c=1;j<=30000&&c<=i;j+=3){
if(j&1){
printf("%d ",j);
c++;
}
}
break;
}
}
}
}
另一种解法:
其实跟上面也差不多,这个比那个好理解点,就是先让其满足互质,最后一个挑和使得符合条件.因为题中说了一定有答案.
所以我们只需要凑出最后一个数即可.
void solve()
{
scanf("%lld",&n);
for(int i=1;cnt<n-1;i++){
if(i%2==0||i%3==0){
a[++cnt]=i;
vis[i]=1;
sum+=i;
}
}
ll r2=sum%2,r3=sum%3;
for(ll i=1;;i++){
if(!vis[i]&&(i+r2)%2==0&&(i+r3)%3==0&&__gcd(i,sum)!=1){
a[++cnt]=i;
break;
}
}
for(int i=1;i<=n;i++){
printf("%lld ",a[i]);
}
}