上海邀请赛前拿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:如果过程中有一个人出错了,那后面的人会跟着错误的来,而不是根据正确的来。
只要注意了这两个坑点,就很容易了。(幸亏想到了这两个坑点。。不然会更被队友嫌弃的。。。。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;
}