fjwc2019 D2T1 直径 (构造)

#181. 「2019冬令营提高组」直径

(这题构造题是我考场上唯一一A的题........)

先看这个特殊的Subtask4

Subtask 4(20pts):$\sqrt{1+8k}$​​ 为整数。

画了几张图,你轻松地发现这是菊花图。

大概就是这样↓

我们暂且设红点的个数为$k$表示菊花树的大小。

显然一棵菊花树的直径数为$k*(k-1)/2$

接下来我们试着以若干棵菊花图的形式构图。

当我们把两棵大小为(a,b)的菊花树连在一起时,

40pts到手

但是对于某些数(如一些大质数),两棵显然是不够的鸭

那么开三棵叭

ans=k1*(k2+k3)+k2*k3,于是我们可以枚举其中两棵子树,推出剩下一棵是否符合条件。

打个code发现3棵树满足的范围远远超过5000000,瞎搞搞就解决了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int k,ans,tp,A,B,C,cnt; bool ok;
int main(){
    freopen("diameter.in","r",stdin);
    freopen("diameter.out","w",stdout);
    scanf("%d",&k);
    if(k==1){printf("2\n1 2 1\n");return 0;}
    int sq=sqrt(8*k+1);
    if(sq*sq==8*k+1){
        for(int i=sqrt(2*k);i*(i-1)<=2*k;++i)
            if(i*(i-1)==2*k){ans=i+1;break;}
        printf("%d\n",ans);
        for(int i=2;i<=ans;++i) printf("1 %d 1\n",i);
        return 0;
    }//subtask 4
    if(k<=4000){
        ans=k+2;
        printf("%d\n",ans);
        printf("1 2 233\n");
        for(int i=3;i<=ans;++i) printf("1 %d 1\n",i);
        return 0;
    }//subtask 1,2
    for(A=1;A<=2499;++A){
        for(B=A;B<=2499;++B){
            int qwq=k-A*B;
            if(qwq<0) continue;
            if(qwq%(A+B)!=0) continue;
            C=qwq/(A+B);
            if(C<1) continue;
            if(A+B+C+4<=5000){ok=1;break;}
        }
        if(ok)break;
    }
    ans=A+B+C+4; cnt=1;
    printf("%d\n",ans);
    for(int i=1;i<=3;++i) ++cnt,printf("1 %d 233\n",cnt);
    for(int i=1;i<=A;++i) ++cnt,printf("2 %d 1\n",cnt);
    for(int i=1;i<=B;++i) ++cnt,printf("3 %d 1\n",cnt);
    for(int i=1;i<=C;++i) ++cnt,printf("4 %d 1\n",cnt);
    return 0;
}

 

posted @ 2019-02-25 07:03  kafuuchino  阅读(187)  评论(0编辑  收藏  举报