APIO2013 T3 Tasksauthor
首先解决
(这道题几乎全部的难点在于
1
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout<<100<<endl;
rp(i,101)cout<<0<<endl;
cout<<1<<endl;
cout<<"1 2"<<endl;
return 0;
}
//Crayan_r
2
那么我们就考虑怎么卡。发现只要下一轮要走的新点编号比原先的点小,就必须下一轮再更新。这样我们连
vt<pii>vv[105];
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout<<100<<endl;
vv[0].pb({99,1});
rep(i,2,99)vv[i].pb({i-1,1});
int cnt=0;
rep(i,1,99){
rep(j,i+1,99){
vv[i].pb({j,999999});
cnt++;
if(cnt==950)break;
}if(cnt==950)break;
}
rd(i,100){
cout<<vv[i].size()<<" ";
for(auto j:vv[i])cout<<j.first<<" "<<j.second<<" ";
cout<<endl;
}
cout<<10<<endl;
rd(_,10)cout<<0<<" "<<1<<endl;
return 0;
}
//Crayan_r
3
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
freopen("f.out","w",stdout);
cout<<100<<endl;
rp(i,101)cout<<0<<endl;
cout<<1<<endl;
cout<<"1 2"<<endl;
return 0;
}
//Crayan_r
4
卡
然后看到这个数字个数限制还非常捉急,这么一点数字,每个点还至少要连一条边,匀下来点数只有
我们来看
这就是一个小小的例子,我们可以构造这样的结构,骗过
如果我们把这样的结构重复
指数级意味着什么呢?意味着我们在第一个结构试错过一次走上对路的时候,依然会把后面所有结构的不优答案再试一遍。那又是什么呢?就是我们每次走对路的优势要从终点到起点递增,大到只要我们当前选的是对的,后面的即使全部选错的,也比当前选错后面全对要小。这样前面轮的答案就不会影响到当前的循环。
也就是,假设我们的每个结构是
那么
我们发现,如果我们设
然后还有什么要求呢?
这样就可以把
vt<pii>vv[305];
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout<<999<<" "<<1501<<endl;
for(int i=32;i>=2;i-=2){
int res=i/2;
vv[i].pb({i-1,1});
vv[i].pb({i-2,0});
vv[i-1].pb({i-2,-(1ll<<(res))});
}
rd(i,33){
cout<<vv[i].size()<<" ";
for(auto j:vv[i])cout<<j.first<<" "<<j.second<<" ";
cout<<endl;
}
cout<<10<<endl;
rd(_,10)cout<<32<<" "<<0<<endl;
return 0;
}
//Crayan_r
5
我们直接把
vt<pii>vv[305];
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout<<300<<endl;
rep(i,1,299)vv[i].pb({i-1,1});
int cnt=0;
rep(i,1,299){
rep(j,i+1,299){
vv[j].pb({i,999999});
cnt++;
if(cnt==37)break;
}if(cnt==37)break;
}
rd(i,300){
cout<<vv[i].size()<<" ";
for(auto j:vv[i])cout<<j.first<<" "<<j.second<<" ";
cout<<endl;
}
cout<<10<<endl;
rd(_,10)cout<<299<<" "<<0<<endl;
return 0;
}
//Crayan_r
6
直接套
vt<pii>vv[305];
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout<<999<<" "<<1501<<endl;
for(int i=32;i>=2;i-=2){
int res=i/2;
vv[i].pb({i-1,1});
vv[i].pb({i-2,0});
vv[i-1].pb({i-2,-(1ll<<(res))});
}
rd(i,33){
cout<<vv[i].size()<<" ";
for(auto j:vv[i])cout<<j.first<<" "<<j.second<<" ";
cout<<endl;
}
cout<<6<<endl;
rd(_,6)cout<<32<<" "<<0<<endl;
return 0;
}
//Crayan_r
7
这个问题只是卡掉这个神秘程序,因为
发现算法强制我们用恰好
那么我们考虑这个神秘程序的工作,其实就是通过编号在前面的点的安排方式进行剪枝。那么我们让它剪不掉就好了。具体而言,我们在前若干个点压根不进行任何限制,让他跑,然后后面的点施加很强的限制(造一堆奇环或者造一个比较小的完全图),导致根本没有方案可以用。这样在
然后我们观察一下下发的程序,发现还有点离谱,只有一次搜索结束之后才会出来判断
vt<pii>vv[1005];
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout<<999<<" "<<1501<<endl;
int cnt=1501;
rep(i,21,997){
cout<<i<<" "<<i+1<<endl;
cnt--;
}
rep(i,21,996){
cout<<i<<" "<<i+2<<endl;
cnt--;
if(!cnt)break;
}
return 0;
}
//Crayan_r
8
我们发现
(让这个程序通过非常简单,随机一个出来就是了)
还是要找靠谱一点的方法的,具体方法就是构造一个二分图,把前
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout<<999<<" "<<1501<<endl;
int cnt=1501;
rep(i,0,448){
cout<<i<<" "<<i+450<<endl;;cnt--;
}cnt--;cout<<449<<" "<<450<<endl;
rep(i,1,449){
rep(j,450,998)if(j!=i+450){
cout<<i<<" "<<j<<endl;cnt--;
if(!cnt)break;
}
if(!cnt)break;
}
return 0;
}
//Crayan_r
然后就通过了。
另外,洛谷的
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?