NOIP2016第二题
题目:https://www.luogu.org/problem/show?pid=2010
周俊豪同学的分析及代码:
var ans,d1,d2,i,k,n,y,r:longint; a:array[1..8] of byte; p:boolean; begin readln(d1,d2); r:=d1 mod 100; d1:=d1 div 100; y:=d1 mod 100; d1:=d1 div 100;//分离年月日 n:=d1; while (n*10000+y*100+r)<=d2 do begin k:=n*10000+y*100+r;//当前的年月日(8位数) for i:=1 to 8 do begin a[i]:=k mod 10; k:=k div 10; end;//分离每个数字 if (a[1]=a[8])and(a[2]=a[7])and(a[3]=a[6])and(a[4]=a[5]) then inc(ans);//判断回文 if ((n mod 4=0)and(n mod 100<>0)) or (n mod 400=0) then p:=true else p:=false;//判断是否为闰年 inc(r);//加一天 if (r=32) and ((y=1)or(y=3)or(y=5)or(y=7)or(y=8)or(y=10)or(y=12)) then begin r:=1; inc(y); end;//大月进位 if (r=31) and ((y=4)or(y=6)or(y=9)or(y=11)) then begin r:=1; inc(y); end;//小月进位 if (r=29) and (y=2) then begin//未加and(p=false),闰年错误 r:=1; y:=3; end;//非闰年2月进位 if (r=30) and (y=2) and p then begin r:=1; y:=3; end;//闰年2月进位 if y=13 then begin inc(n); y:=1; end;//年进位 end; writeln(ans);//输出 end.
韩天意同学的分析及代码:
var a1,b1,i,n,y,r,g,s1,s2,ans,z,f,i1:longint; a,b:string; j:array[1..8]of byte; begin assign(input,'date.in'); reset(input); assign(output,'date.out'); rewrite(output); readln(a);//以字符串的形式读入2个日期 readln(b); ans:=0; for i:= 1 to 8 do a1:=a1*10+(ord(a[i])-48); for i:= 1 to 8 do b1:=b1*10+(ord(b[i])-48);//把字符串转回数字 for i:=a1 to b1 do begin i1:=i;// n:=i div 10000;//计算出年 y:=(i mod 10000) div 100;//计算出月 r:=i mod 100;//计算出日 if (y>=1) and (y<=12) then begin//判断月份是否存在 case y of//判断月份中应有多少日子 1,3,5,7,8,10,12: g:=31; 4,6,9,11:g:=30; 2:if (n mod 400=0)or((n mod 100<>0) and(n mod 4=0))then g:=29 else g:=28; end; if (r>=1)and(r<=g)then begin//判断日期是否在范围内 f:=100000000; for z:=1 to 8 do begin f:=f div 10; j[z]:=i1 div f; i1:=i1 mod f; end;//把数字转换成数组,方便判断是否是回文 s1:=1;s2:=8; while s1<s2 do begin if j[s1]=j[s2] then begin inc(s1);dec(s2);end else break; end; if s1>s2 then ans:=ans+1;//判断回文 end; end; end; writeln(ans); close(input); close(output); end. 这道题使用字符串完全是多余的。使用for语句来暴力搜索过慢导致了:虽然检查后答案都对,却有超时。只得到70分。要拿满分 经查看他人题解,发现另有个简单的方法,代码如下: var a:array [1..12] of longint=(31,28,31,30,31,30,31,31,30,31,30,31); date1,date2,i,ans,r1,y1,r2,y2,m,d:longint; function use(y:longint):boolean; begin d:=y div 100; m:=y mod 100; d:=(d mod 10)*10+d div 10; m:=(m mod 10)*10+m div 10; if ((m>=1)and(m<=12))and((d>=1)and(d<=a[m])) then begin ans:=ans+1;exit(true);end else exit(false); end; begin read(date1,date2); y1:=date1 mod 10000 div 100;r1:=date1 mod 100;y2:=date2 mod 10000 div 100;r2:=date2 mod 100; for i:=date1 div 10000 to date2 div 10000 do begin if (i mod 4=0)and((i mod 100<>0)or(i mod 400=0)) then a[2]:=29 else a[2]:=28; if (use(i)) then begin if ((i=date1 div 10000)and(m<y1))or((i=date1 div 10000)and(m=y1)and(d<r1)) then ans:=ans-1; if ((m>y2)and(i=date2 div 10000))or((m=y2)and(i=date2 div 10000)and(d>r2))then ans:=ans-1; end; end; write(ans); end.
刘可盈的分析及代码:
var date1,date2,i,d,y,m,yy,dm,ans:longint; begin assign(input,'date.in');reset(input); assign(output,'date.out');rewrite(output); readln(date1); readln(date2); ans:=0; for i:=date1 to date2 do begin // 从date1循环到date2 y:=i; //把年月日算出来 d:=y mod 100; y:=y div 100; m:=y mod 100; y:=y div 100; case m of //把不正确的日期去掉 1,3,5,7,8,10,12:if d>31 then continue; 4,6,9,11:if d>30 then continue; 2:if ((y mod 4=0) and (y mod 100<>0)) or (y mod 400=0) then if d>29 then continue else if d>28 then continue; else continue; end; yy:=0; while y>0 do begin //把年份倒过来 yy:=yy*10+(y mod 10); y:=y div 10; end; dm:=m*100+d; //把月份和日期放在一起 if dm=yy then ans:=ans+1; //检查是否是回文 end; writeln(ans); close(input); close(output); end.