[SNCPC2019] To the Park 题解
来自某不愿意透露姓名的队友。
很好玩的构造。
首先考虑答案的上界,很明显
然后考虑构造符合这个上界的答案。由于偶数和偶数之间可以相互配对,所以我们可以先考虑奇数,而奇数中奇素数是比较特别的。对于小于
这样我们可以保证所有大于
一个坑点是线性筛不能只筛到
#include<bits/stdc++.h>
using namespace std;
typedef int ll;
typedef long long int li;
const ll MAXN=1e5+51;
vector<pair<ll,ll> >v;
vector<ll>v2;
ll test,n,ptot,x,y,res;
ll np[MAXN],prime[MAXN],c[MAXN];
inline ll read()
{
register ll num=0,neg=1;
register char ch=getchar();
while(!isdigit(ch)&&ch!='-')
{
ch=getchar();
}
if(ch=='-')
{
neg=-1;
ch=getchar();
}
while(isdigit(ch))
{
num=(num<<3)+(num<<1)+(ch-'0');
ch=getchar();
}
return num*neg;
}
inline void sieve(ll limit)
{
np[1]=1;
for(register int i=2;i<=limit;i++)
{
if(!np[i])
{
prime[++ptot]=i;
}
for(register int j=1;i*prime[j]<=limit;j++)
{
np[i*prime[j]]=1;
if(i%prime[j]==0)
{
break;
}
}
}
}
inline void solve()
{
n=read();
if(n<=3)
{
return (void)puts("0");
}
v.clear(),v2.clear(),c[1]=1;
for(register int i=2;i<=n;i++)
{
c[i]=0;
}
for(register int i=1;prime[i]<=n;i++)
{
prime[i]>(n>>1)?(c[prime[i]]=1):1;
}
for(register int i=(n>>1);i>=3;i--)
{
if(np[i])
{
continue;
}
v2.push_back(i);
for(register int j=3;j*i<=n;j++)
{
!c[j*i]?(void)v2.push_back(j*i):(void)1;
}
v2.size()&1?(void)v2.push_back(i<<1):(void)1;
for(register int j=0;j<v2.size()-1;j+=2)
{
x=v2[j],y=v2[j+1],v.push_back(make_pair(x,y)),c[x]=c[y]=1;
}
v2.clear();
}
for(register int i=1;i<=n;i++)
{
!c[i]?(void)v2.push_back(i):(void)1;
}
for(register int i=0;i<v2.size()-1;i+=2)
{
x=v2[i],y=v2[i+1],v.push_back(make_pair(x,y)),c[x]=c[y]=1;
}
printf("%d ",res=v.size());
for(register int i=0;i<res;i++)
{
printf("%d %d",v[i].first,v[i].second);
i!=res-1?putchar(' '):1;
}
puts("");
}
int main()
{
test=read(),sieve(100030);
for(register int i=1;i<=test;i++)
{
solve();
}
}