2017年多校联合训练 第六场(福州大学)

官方题解
1002 Mindis
hdoj6097题目链接
几何方法:
将点P关于圆O的反演点记作P',由定义得OP*OP'= r2 ,则△ODP~△ODP',相似比为OP:R,点Q同理
当反演点的连线与圆有交点时,min(DP+DQ)转化为min(DP'+DQ')*相似比
否则D即为△OPQ中从点O出发的角平分线(等腰三角形三线合一)与圆的交点,计算DP+DQ
代码种用复数形式记录点,abs( )返回模值,norm( )返回模的平方

#include
using namespace std;
typedef complex<double> V;
int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        double r,x,y,s;
        scanf("%lf",&r);
        scanf("%lf%lf",&x,&y);
        V p=V(x,y);
        scanf("%lf%lf",&x,&y);
        V q=V(x,y);
        if(p==q) s=2*(r-abs(p)); //特殊情况:两点重合
        else{
            V pp=p*r*r/norm(p);
            V qq=q*r*r/norm(q);
            if(norm(pp)-norm(pp-qq)/4<=r*r) s=abs(pp-qq)*abs(p)/r; //△OP'Q'的高小于等于R,则反演点连线与圆O有交点
            else{
                V mid=p+q;
                if(p==-q) mid=V(-p.imag(),p.real());
                mid=mid/abs(mid)*r; //mid表示角平分线与圆的交点
                s=2*abs(mid-p);
            }
        }
        printf("%.7f\n",s);
    }
}

1003 Inversion
hdoj6098题目链接
优雅的暴力做法:
排序后找到下标不能整除当前下标的最大值

#include
using namespace std;
struct node
{
    int v,p;
    bool operator < (const node& x) const { return v>x.v; }
}a[100005];
int main()
{
    int t,n,i,j;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        for(i=1;i<=n;i++) scanf("%d",&a[i].v),a[i].p=i;
        sort(a+1,a+1+n);
        for(i=2;i<=n;i++){
            for(j=1;j<=n&&a[j].p%i==0;j++);
            printf("%d%c",a[j].v,i==n?'\n':' ');
        }
    }
}

1008 Kirinriki
hdoj6103题目链接
回文串,枚举对称轴,双指针维护

#include
using namespace std;
int main()
{
    int t,m,len,ans,cnt,sum,l,x,r,y,i;
    char s[5005];
    scanf("%d",&t);
    while(t--){
        scanf("%d%s",&m,s+1);
        len=strlen(s+1);
        ans=0;
        for(i=2;i//以下标为i的字符为对称轴
            l=x=i-1,r=y=i+1;
            cnt=sum=0;
            while(l&&r<=len){
                sum+=abs(s[l]-s[r]),cnt++;
                if(sum<=m) ans=max(ans,cnt);
                else{
                    while(sum>m){
                        sum-=abs(s[x]-s[y]);
                        x--,y++;
                        cnt--;
                    }
                }
                l--,r++;
            }
        }
        for(i=1;i//以下标为i的字符右侧间隙为对称轴
            l=x=i,r=y=i+1;
            cnt=sum=0;
            while(l&&r<=len){
                sum+=abs(s[l]-s[r]),cnt++;
                if(sum<=m) ans=max(ans,cnt);
                else{
                    while(sum>m){
                        sum-=abs(s[x]-s[y]);
                        x--,y++;
                        cnt--;
                    }
                }
                l--,r++;
            }
        }
        printf("%d\n",ans);
    }
}

1010 Gameia
hdoj6105题目链接
//比赛最后1h开了这题,菜鸡QYQ和Dsaitou玩了好几把,一直没啥头绪。只见lza11111一眼看穿规律,1A,撒花
如果Bob能把这棵树分成若干两个一组的点对,那么Bob取得胜利,否则Alice获胜:
代码中首先特判了结点个数为奇,Bob超能力使用次数不够的情况,都是Alice获胜。
然后暴力枚举叶子结点,若存在有多个儿子节点时叶子节点的情况,那么Alice获胜。

#include
using namespace std;
#define N 505
int main()
{
    int t,n,k,d[N],f[N],i,j,fg;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&k);
        memset(d,0,sizeof(d));
        for(i=2;i<=n;i++) scanf("%d",&f[i]),d[i]++,d[f[i]]++;
        if(n&1||k2-1) { puts("Alice");continue; }
        for(fg=0,i=2;i<=n;i++)if(d[i]==1){
            for(j=i+1;j<=n;j++)if(f[i]==f[j]&&d[j]==1) { fg=1;break; }
        }
        puts(fg?"Alice":"Bob");
    }
}

1011 Classes
hdoj6106题目链接
签到快乐

#include
using namespace std;
int main()
{
    int t,n,mx,a,b,c,ab,bc,ac,abc;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        mx=0;
        while(n--){
            scanf("%d%d%d%d%d%d%d",&a,&b,&c,&ab,&bc,&ac,&abc);
            ab-=abc,bc-=abc,ac-=abc;
            if(ab<0||bc<0||ac<0) continue;
            a-=ab+ac+abc,b-=bc+ab+abc,c-=bc+ac+abc;
            if(a<0||b<0||c<0) continue;
            mx=max(mx,a+b+c+ab+bc+ac+abc);
        }
        printf("%d\n",mx);
    }
}

你可能感兴趣的:(HDU,2017年多校联合训练)