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;
}