P11436 题解
dAniel_lele · · 题解
神秘 adhoc。
首先你考虑一下最大多少,然后你会发现每个非
然后你会发现你搓个 DAG 答案必然是每个点入边数量之积,所以你不能搓 DAG。
这引导我们去搓一个环。对于一个单独的环(
但是这样还是不够,我们只能弄出
考虑搓一个环,然后加一条
我们钦定
然后再加上
这启发我们求出要减去的部分,然后对减去的部分三进制分解,依次加入边。也就是,对于第
构造会有一些 corner case,所以可以找到比
#include <bits/stdc++.h>
#define int long long
#define mid ((l+r)>>1)
#define lowbit(i) (i&(-i))
using namespace std;
int a[40],b[40],c[40],cnt;
void solve(){
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
int n; cin>>n;
if(n==1){
cout<<1<<" "<<0<<"\n";
return ;
}
int now=1,cnted=0;
cnt=0;
while(now<n){
if(now*2>=n){
now*=2;
a[++cnt]=3;
a[1]=2;
cnted+=2;
}
else{
now*=3;
a[++cnt]=3;
cnted+=3;
}
}
if(now==n){
cout<<cnt+1<<" "<<cnted<<"\n";
for(int i=1;i<=cnt;i++){
for(int j=1;j<=a[i];j++) cout<<1<<" "<<i+1<<"\n";
}
return ;
}
if(cnted==101){
cnt--;
a[1]=3;
a[cnt]=4;
cnted=100;
}
for(int i=1;i<=cnt;i++) c[i]=1;
c[2]=0;
int ex=now-n,it=2;
while(ex){
int md=ex%3; ex/=3;
b[it]=md;
it++;
}
cout<<cnt+1<<" "<<cnted<<"\n";
for(int i=1;i<=cnt;i++){
if(i==1){
if(a[1]==3) cout<<1<<" "<<2<<"\n";
cout<<1<<" "<<2<<"\n";
cout<<cnt+1<<" "<<2<<"\n";
continue;
}
for(int j=1;j<=c[i];j++) cout<<i<<" "<<i+1<<"\n";
for(int j=1;j<=b[i];j++) cout<<2<<" "<<i+1<<"\n";
for(int j=1;j<=a[i]-c[i]-b[i];j++) cout<<1<<" "<<i+1<<"\n";
}
}
signed main(){
int t; cin>>t;
while(t--) solve();
return 0;
}