题解:P16344 [科大国创杯初中组 2026] 构造题
通过二进制拆分,给出一种只用 24 个顶点,64 条边的构造方式。
分析
总共用
考虑对
Step 1
每
-
i \to i+1 -
i \to i+2 -
i+1 \to i+2
此时发现
像这样构造(把
Step 2
类似模块一,将
类似模块一和模块二,将
Step3
考虑将模块二和模块三混联来平衡节点数和边数,这里给出一种构造方式(构造方式不唯一):使用
具体细节看代码。
代码
#include<bits/stdc++.h>
using namespace std;
int d[100]={1,3,4,5,7,8,9,11,12,14,15,17,18,20,21,22,23};
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 14 15
// 表示d[i]条边连到24,上面那行注释为不同d[i]连到24方案数对应的二次幂 ,2^16用2^15+2^14+2^14表示,因为p最大为75000所以2^16+2^13+...完全够用
int vis[100];
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
//freopen("construct.in","r",stdin);
//freopen("construct.out","w",stdout);
int p;
cin>>p;
cout<<24<<" "<<64<<endl;
for(int i=1;i<=5;i+=4){//模块3
int q=i+4;
for(int j=i;j<=q;j++){
for(int x=j+1;x<=q;x++){
cout<<j<<" "<<x<<endl;
}
}
}
for(int i=9;i<=18;i+=3){//模块2
int q=i+3;
for(int j=i;j<=q;j++){
for(int x=j+1;x<=q;x++){
cout<<j<<" "<<x<<endl;
}
}
}
//连最后一个模块2
cout<<21<<" "<<22<<endl;
cout<<21<<" "<<23<<endl;
cout<<22<<" "<<23<<endl;
//连到24的边
for(int i=0;i<17;i++){
cout<<d[i]<<" "<<24<<endl;
}
for(int i=0;i<=p;i++){
int t=i;
if(t>=65536){//特殊处理 2^16用2^15+2^14+2^14表示
t-=65536;
vis[16]=1,vis[15]=1,vis[14]=1;
}
if(t>=32768){
t-=32768;
vis[16]=1;
}
if(t>=16384){
t-=16384;
vis[15]=1;
}
for(int j=16384,jj=14;j>=1;j/=2,jj--){
if(t>=j){
t-=j;
vis[jj]=1;
}
}
for(int j=1;j<=47;j++)cout<<1;
for(int j=0;j<17;j++){
cout<<vis[j];
vis[j]=0;
}
cout<<endl;
}
return 0;
}