div1难度的挑战赛属实难顶,只能勉强做两题。
A题比较简单,优先塞2,如果有空余就补1。
本来一开始还在慢悠悠的一次一次塞,后来发现数据太大了,改了下算法。
#include<stdio.h> int main() { int t; scanf("%d",&t); long long add,m,n,k,s,temp,temp2; while(t--) { s=0; scanf("%lld %lld %lld",&m,&n,&k); s+=(n/(k/2)); //printf("%d ",s); m-=(k%2)*s; //printf("%d ",m); n-=(k/2)*s; //printf("%d ",n); if(m>0||n>0) { s++; m-=(k-2*n); //printf("%d ",m); n=0; } if(m>0) { s+=m/k; if(m%k!=0) s++; } printf("%lld\n",s-1); } return 0; }
B题给定a,b,构造一个有a割点b桥的无自环、无重边、连通图。
不难,就是特别烦。分四种情况:1.ab均为0,输出一个三角形即可。2.a为0时b>2,此时无解。3.a>1时b为0,输出若干四边形(形如[1 2],[1 3],[2 4],[3 4],[4 5],[4 6],[4 7],[4 8],这样4就是一个割点,看起来像是用4连接起来两个四边形)。
4.a>1,b>1。先记录一下a和b谁更大,然后构造形如[4 5],[5 6],[6 7]这样的图,这时候割点和桥数量相当,直至割点耗尽或桥耗尽。
如果还剩割点,就接着画四边形。如果还剩桥,就在4处构造额外的桥,因为4本身是割点,所以这时候构造桥不需要加割点。
没注意到a和b导致输入的时候顺序反了下。注意点的数量一定要和构造出的相同,不然会有孤立的点导致不连通。边的数量也要正确,否则会输出不正确。因为边数的问题wa了很多次。
2020/6/23更新:这做法属实笨。实际上桥和割点可以分开构造,会简洁和方便很多。
#include<stdio.h> int main() { int add,add2,S,a,b; scanf("%d %d",&b,&a); S=0; if(b==0&&a==0) { printf("3 3\n1 2\n2 3\n3 1\n"); return 0; } if(a>1&&b==0) { printf("-1"); return 0; } if(a==0&&b>0) { printf("%d %d\n",b*3+4,(b+1)*4); for(add2=0;add2<=b;add2++) { printf("%d %d\n%d %d\n%d %d\n%d %d\n", add2*3+1,add2*3+2,add2*3+1,add2*3+3, add2*3+2,add2*3+4,add2*3+3,add2*3+4); } return 0; } /*if(a==1&&b>1) { printf("%d %d\n",b+1,b); for(add2=2;add2<=b+1;add2++) printf("1 %d\n",add2); return 0; }*/ if(b<a-1) { S=a-b-1; } if(b==a-1) { printf("%d %d\n",a+1,a); for(add=1;add<=a;add++) printf("%d %d\n",add,add+1); return 0; } if(S>0) { printf("%d %d\n",b+4+(-1)*3+3+S+1,4*0+4+a); a=b; } else printf("%d %d\n",a+4+(b-a-1)*3+3,4*(b-a)+4+a+S); printf("1 2\n1 3\n2 4\n3 4\n"); if(S>0) for(add2=1;add2<=S+1;add2++) { printf("4 %d\n",a+4+(-1)*3+3+add2); } for(add=1;add<=a;add++) { printf("%d %d\n",add+3,add+4); } //最后的点是a+4 ,=add+2 for(add=a+4,add2=0;add2<=b-a-1;add2++) { printf("%d %d\n%d %d\n%d %d\n%d %d\n", add+add2*3,add+add2*3+1,add+add2*3,add+add2*3+2, add+add2*3+1,add+add2*3+3,add+add2*3+2,add+add2*3+3); } return 0; }