首页 > 代码库 > 2013年成都邀请赛解题报告

2013年成都邀请赛解题报告

上海邀请赛前拿2013年的成都邀请赛热身,比赛结果大大出乎了我们的预期啊。。。没做出来的几道题可能还会更新的。

A题:

题目地址:HDU 4716

水题。。这题是我敲的。。敲麻烦了。。。sad。。。你们就当没看见吧。。。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;

int main()
{
    char s[20][20];
    int t, x;
    int i, j, num=0;
    scanf("%d",&t);
    while(t--)
    {
        num++;
        scanf("%d",&x);
        printf("Case #%d:\n",num);
        x=x/10;
        s[0][0]='*';
        s[0][13]='*';
        s[11][0]='*';
        s[11][13]='*';
        for(i=1;i<13;i++)
        {
            s[0][i]='-';
            s[11][i]='-';
        }
        for(i=1;i<11;i++)
        {
            s[i][0]='|';
            s[i][13]='|';
        }
        for(i=1;i<=10-x;i++)
        {
            for(j=1;j<=12;j++)
            {
                s[i][j]='.';
            }
        }
        for(i=10-x+1;i<=10;i++)
        {
            for(j=1;j<=12;j++)
            {
                s[i][j]='-';
            }
        }
        for(i=0;i<=11;i++)
        {
            for(j=0;j<=13;j++)
            {
                printf("%c",s[i][j]);
            }
            printf("\n");
        }
    }
    return 0;
}

E题:

题目地址:HDU4720

不是我做的。。。计算几何题不想做。。。。队友说是模板题。

代码例如以下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
struct Point
{
    double x;
    double y;
} pt[1005];
struct Circle
{
    struct Point center;
    double r;
};
struct Traingle
{
    struct Point p[3];
};
double Dis(struct Point p,struct Point q)
{
    double dx=p.x-q.x;
    double dy=p.y-q.y;
    return sqrt(dx*dx+dy*dy);
}
double Area(struct Traingle ct)
{
    return fabs((ct.p[1].x-ct.p[0].x)*(ct.p[2].y-ct.p[0].y)-(ct.p[2].x-ct.p[0].x)*(ct.p[1].y-ct.p[0].y))/2.0;
}
struct Circle CircumCircle(struct Traingle t)
{
    struct Circle tmp;
    double a,b,c,c1,c2;
    double xA,yA,xB,yB,xC,yC;
    a=Dis(t.p[0],t.p[1]);
    b=Dis(t.p[1],t.p[2]);
    c=Dis(t.p[2],t.p[0]);
    tmp.r=(a*b*c)/(Area(t)*4.0);
    xA=t.p[0].x;
    yA=t.p[0].y;
    xB=t.p[1].x;
    yB=t.p[1].y;
    xC=t.p[2].x;
    yC=t.p[2].y;
    c1=(xA*xA+yA*yA-xB*xB-yB*yB)/2.0;
    c2=(xA*xA+yA*yA-xC*xC-yC*yC)/2.0;
    tmp.center.x=(c1*(yA-yC)-c2*(yA-yB))/((xA-xB)*(yA-yC)-(xA-xC)*(yA-yB));
    tmp.center.y=(c1*(xA-xC)-c2*(xA-xB))/((yA-yB)*(xA-xC)-(yA-yC)*(xA-xB));
    return tmp;
};
int main()
{
    struct Traingle tt;
    Point qq;
    Circle cc;
    double l1,l2,l3;
    int t,k=1;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lf %lf",&tt.p[0].x,&tt.p[0].y);
        scanf("%lf %lf",&tt.p[1].x,&tt.p[1].y);
        scanf("%lf %lf",&tt.p[2].x,&tt.p[2].y);
        scanf("%lf %lf",&qq.x,&qq.y);
        l1=Dis(tt.p[0],tt.p[1]);
        l2=Dis(tt.p[0],tt.p[2]);
        l3=Dis(tt.p[2],tt.p[1]);
        if(((l1*l1)+(l2*l2)<(l3*l3))||((l3*l3)+(l2*l2)<(l1*l1))||((l1*l1)+(l3*l3)<(l2*l2)))
        {
            if(((l1*l1)+(l2*l2)<(l3*l3)))
            {
                cc.r=l3/2.0;
                cc.center.x=(tt.p[1].x+tt.p[2].x)/2.0;
                cc.center.y=(tt.p[1].y+tt.p[2].y)/2.0;
            }
            else if(((l3*l3)+(l2*l2)<(l1*l1)))
            {
                cc.r=l1/2.0;
                cc.center.x=(tt.p[1].x+tt.p[0].x)/2.0;
                cc.center.y=(tt.p[1].y+tt.p[0].y)/2.0;
            }
            else if(((l1*l1)+(l3*l3)<(l2*l2)))
            {
                cc.r=l2/2.0;
                cc.center.x=(tt.p[0].x+tt.p[2].x)/2.0;
                cc.center.y=(tt.p[0].y+tt.p[2].y)/2.0;
            }
        }
        else{
            cc=CircumCircle(tt);
        }
        //printf("%.2lf %.2lf\n",cc.center.x,cc.center.y);
        //printf("%.2lf %.2lf\n",cc.r,Dis(qq,cc.center));
        printf("Case #%d: ",k++);
        if(Dis(qq,cc.center)<=cc.r)
            printf("Danger\n");
        else printf("Safe\n");
    }
    return 0;
}

G题:

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4722

额。。这题听学长说是DP?好吧。。无论了,反正我推得规律做出来了。。。

这题的规律在于从XXX0到XXX9(X指随意数,随意位数,比方12340至12349或111111110至111111119这种)中间,他们的各位和是递增1的,并且刚好递增了10,也就是说每个这种10个数的周期都是有且仅仅有1个刚好能被10整除的,所以对于随意的区间内仅仅要找到有多少个这种周期就可以。然后再遍历找出前面和后面多余的。比方5至35,遍历找到前面多余的5到9,没有,再遍历后面多余的30到35,没有,然后中间的10到29是两个周期,直接加上2.于是2就算出来了。仅仅须要遍历最多20个数,剩下的能够计算出来。由于int64被坑了3次WA。。。

代码例如以下:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
__int64 num=0, i, j, x, y, t, a, b, s, sum, pos1, pos2, flag1, flag2, z;
int main()
{

    scanf("%I64d",&t);
    while(t--)
    {
        s=0;
        num++;
        flag1=flag2=0;
        scanf("%I64d%I64d",&a, &b);
        for(i=a; i<=b; i++)
        {
            x=i;
            y=i;
            sum=0;
            while(x)
            {
                z=x%10;
                sum+=z;
                x=x/10;
            }
            if(sum%10==0)
            {
                s++;
            }
            if(y%10==9)
            {
                pos1=y+1;
                flag1=1;
                break;
            }
        }
        if(flag1==1)
        {
            for(i=b; i>=pos1; i--)
            {
                x=i;
                y=i;
                sum=0;
                while(x)
                {
                    z=x%10;
                    sum+=z;
                    x=x/10;
                }
                if(sum%10==0)
                {
                    s++;
                }
                if(y%10==0)
                {
                    pos2=y-1;
                    flag2=1;
                    break;
                }
            }
        }
        if(flag1==1&&flag2==1)
            s+=(pos2-pos1+1)/10;
        printf("Case #%I64d: %I64d\n",num,s);
    }
    return 0;
}


K题:

题目地址:HDU 4726

思路是跟队友讨论的,但代码不是我敲的。。细节我也不清楚。。

详细思路是保存上下每一个数字的出现次数,然后依据次数直接计算,而不是一个个查找。对于第一位数字须要特判,不能出现9+0的这样的情况。然后从和为9的组合開始查找(事实上不能叫查找。。直接哈希)。

代码例如以下:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
char str1[2000000] ;
char str2[2000000] ;
int main()
{
    int k , i , j , l ;
    int s1[11] , s2[11] , ss[11] ;
    int t , tt ;
    scanf("%d", &t);
    for(tt = 1 ; tt <= t ; tt++)
    {
        memset(s1,0,sizeof(s1));
        memset(s2,0,sizeof(s1));
        memset(ss,0,sizeof(ss));
        scanf("%s%s", str1, str2);
        l = strlen(str1) ;
        for(i = 0 ; i < l ; i++)
        {
            s1[ str1[i]-'0' ]++ ;
            s2[ str2[i]-'0' ]++ ;
        }
        if( l == 1 && ( s1[0] == 1 || s2[0] == 1 ) )
        {
            if(s1[0] == 1)
            {
                printf("Case #%d: %c\n", tt, str2[0]);
            }
            else
            {
                printf("Case #%d: %c\n", tt, str1[0]);
            }
            continue ;
        }
        printf("Case #%d: ", tt);
        int mm = -1 , m , mi , mj ;
        for(i = 1 ; i <= 9 ; i++)
            for(j = 1 ; j <= 9 ; j++)
            {
                if( s1[i] && s2[j] )
                {
                    m = i + j ;
                    m %= 10 ;
                    if(m >mm)
                    {
                        mm = m ;
                        mi = i ;
                        mj = j ;
                    }
                }
            }
        printf("%d", mm);
        if(mm == 0)
        {
            printf("\n");
            continue ;
        }
        s1[mi]-- ;
        s2[mj]-- ;
        for(k = 9 ; k >= 0 ; k--)
        {
            if(k == 7)
                k = 7 ;
            for(i = 0 ; i <= 9 ; i++)
                for(j = 0 ; j <= 9 ; j++)
                {
                    if( s1[i] && s2[j] && (i+j)%10 == k )
                    {
                        m = min(s1[i],s2[j]) ;
                        ss[k] += m ;
                        s1[i] -= m ;
                        s2[j] -= m ;
                    }
                }
        }
        for(i = 9 ; i >= 0 ; i--)
        {
            for( j = ss[i] ; j > 0 ; j--)
            {
                printf("%d", i) ;
            }
        }
    printf("\n");
    }
    return 0;
}


L题:

题目地址:HDU 4727

这题不难,但非常坑!!这也是我被队友嫌弃的一道题。。sad。。。没写Case就直接提交了。。。简直sad。。。

须要注意的两个坑点是

1:第一个人也是会出错的,所以当发现后面都没出错后,那就是第一个出错了。

2:假设过程中有一个人出错了,那后面的人会跟着错误的来,而不是依据正确的来。

仅仅要注意了这两个坑点,就非常easy了。(幸亏想到了这两个坑点。。不然会更被队友嫌弃的。。。。sad。。)

代码例如以下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
int a[1000000];
int main()
{
    int t, num=0, n, i, j, x;
    scanf("%d",&t);
    while(t--)
    {
        num++;
        scanf("%d",&n);
        x=0;
        int pos;
        for(i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
        }
        for(i=1;i<n;i++)
        {
            if(a[i]!=a[i-1]+1)
            {
                x++;
                pos=i;
            }
        }
        printf("Case #%d: ",num);
        if(x==1)
            printf("%d\n",pos+1);
        else
            printf("1\n");
    }
    return 0;
}


2013年成都邀请赛解题报告