A - 18岁生日
Gardon的18岁生日就要到了,他当然很开心,可是他突然想到一个问题,是不是每个人从出生开始,到达18岁生日时所经过的天数都是一样的呢?似乎并不全都是这样,所以他想请你帮忙计算一下他和他的几个朋友从出生到达18岁生日所经过的总天数,让他好来比较一下。
Input
一个数T,后面T行每行有一个日期,格式是YYYY-MM-DD。如我的生日是1988-03-07。
Output
T行,每行一个数,表示此人从出生到18岁生日所经过的天数。如果这个人没有18岁生日,就输出-1。
主要是考虑闰年的2月会有29号,一般人的18岁会经历4个闰年(闰年的判断条件是能被4整除,不能被100整除,后者可以被400整除,一般情况下4年一个轮回),所以先计算出一般人的天数,然后判断当他出生那年是否为闰年,并且是否在2月及以前出生,是则加1,然后判断18岁那年是否为闰年,并且生日在2月以后,是则加1,除了这两个还有两种情况,当他1岁那年是闰年,那么他17岁的时候也是闰年,会经历5个闰年,也要加1,还有最后一种情况就是,他的0到18岁中途只有三个闰年的,例如他是1885年出生的,其中经历的1900年不是闰年,他总共只经历了3个闰年,但是最初计算的一般值是有4个闰年,所以要减1.
#include <iostream> #include<cstdio> using namespace std; int main() { int t; scanf("%d",&t); while(t--) { int year,mon,day; scanf("%d-%d-%d",&year,&mon,&day); int alld=18*365+4; //一般情况下的总数 if((year%4==0&&year%100!=0)||year%400==0) { if(mon<=2) { if(mon==2&&day==29) {printf("-1\n"); continue;} else alld+=1; } } else{ if(year%4==3) alld+=1; else{ int y=year+18; if((y%4==0&&y%100!=0)||y%400==0) { if(mon>2) alld+=1; } } } if(year%100>82&&year%400<382) alld-=1; //他的18年中(除去出生那年和18那年)包含有能被4整除的不是闰年的情况 printf("%d\n",alld); } return 0; }
E - 圆有点挤
gg最近想给女友送两个精美的小礼品:两个底面半径分别为R1和R2的圆柱形宝石,并想装在一个盒子里送给女友。好不容易找到了一个长方体的盒子,其底面为A*B的矩形,他感觉好像宝石装不进去,但又不敢轻易塞进去试试。现请你帮他判断两个宝石能否放进盒子里(宝石只能竖直放置,且不能堆叠)。
Input
输入的第一行是一个整数,为数据的组数t(t<=1000)。
每组数据占一行,包括4个数A,B,R1,R2,均为不超过1e4的正整数。
Output
对于每组数据,若两个宝石能放进盒子中,则输出YES,否则输出NO。
我最初想到的就是建坐标系,长为a,宽为b,大圆半径为r1,小圆半径为r2,把两个圆都紧靠着矩形的两个对角,大圆圆心的坐标为(r1,r1),小圆圆心坐标为(a-r2,b-r2),然后求两个圆心之间的距离是否大于两个圆的半径之和,大于等于则说明可以放进去。做的时候考虑太多东西了,结果一直没做出来,简直是郁闷,最后不考虑之前的,只考虑了两个圆单独放是否能放进去就可以了,也就是两个圆的直径都要小于矩形的长和宽。
#include <iostream> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; int main() { int t; scanf("%d",&t); while(t--) { int a,b,r1,r2; scanf("%d%d%d%d",&a,&b,&r1,&r2); if(a<b) swap(a,b); if(r1<r2) swap(r1,r2); if(2*r1>b) { printf("NO\n"); continue; } int x=b-r2-r1,y=a-r1-r2; int z=r1+r2; if(x*x+y*y>=z*z) printf("YES\n"); else printf("NO\n"); } return 0; }
G - 开门人和关门人
每天第一个到机房的人要把门打开,最后一个离开的人要把门关好。现有一堆杂乱的机房签 到、签离记录,请根据记录找出当天开门和关门的人。
Input
测试输入的第一行给出记录的总天数N ( > 0 )。下面列出了N天的记录。 每天的记录在第一行给出记录的条目数M ( > 0 ),下面是M行,每行的格式为 证件号码 签到时间 签离时间 其中时间按“小时:分钟:秒钟”(各占2位)给出,证件号码是长度不超过15的字符串。
Output
对每一天的记录输出1行,即当天开门和关门人的证件号码,中间用1空格分隔。 注意:在裁判的标准测试输入中,所有记录保证完整,每个人的签到时间在签离时间之前, 且没有多人同时签到或者签离的情况。
刚做的时候想的是把签到和签退的时间都分时,分,秒,分别记录在一个结构体中,然后排序的时候先按签到的时排序,然后再对时相等的按分排序,再同样对秒排序,最后输出第一位名字,然后同样对签退时间按大到小排序,输出第一位名字,后来知道了一种比较简单的方法,直接用strcmp比较字符串的大小,因为他时间的格式都是一样的,所以可以直接比较。strcmp(a,b)表示a和b字符串相比较,返回a中的字符
与b中字符
的ASCLL码的差值。
#include <iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; struct cheak { char name[20],in[20],out[20]; }c[10000]; int main() { int t; scanf("%d",&t); while(t--) { int n; scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%s%s%s",c[i].name,c[i].in,c[i].out); } for(int i=0;i<n;i++) { struct cheak t; int xx=strcmp(c[0].in,c[i].in); if(xx>0) { t=c[i]; c[i]=c[0]; c[0]=t; } } printf("%s ",c[0].name); for(int i=0;i<n;i++) { struct cheak t; int yy=strcmp(c[i].out,c[0].out); if(yy>0) { t=c[i]; c[i]=c[0]; c[0]=t; } } printf("%s\n",c[0].name); } return 0; }