ZOJ_3950_How Many Nines 解题报告及如何对程序进行测试修改
The 17th Zhejiang University Programming Contest Sponsored by TuSimple
Solution:
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main() 5 { 6 long month[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}; 7 long month_leap[13]={0,31,29,31,30,31,30,31,31,30,31,30,31}; 8 long tmonth[13],tmonth_leap[13]; 9 long t,i,j,k,l,s,g,y1,m1,d1,y2,m2,d2,run1,run2,ans=0; 10 long ge[10000]={0},line[10000]; 11 tmonth[0]=0; 12 tmonth_leap[0]=0; 13 for (i=1;i<12;i++) 14 { 15 tmonth[i]=tmonth[i-1]+month[i]; 16 tmonth_leap[i]=tmonth_leap[i-1]+month_leap[i]; 17 } 18 //between 2000-01-01 and 9999-12-31 19 //the number of "9" in a year(do in advance) 20 for (i=2;i<=9;i++) 21 for (j=0;j<=9;j++) 22 for (k=0;k<=9;k++) 23 for (l=0;l<=9;l++) 24 { 25 s=i*1000+j*100+k*10+l; 26 //the number of 9 in "ijkl" 27 g=((i==9)+(j==9)+(k==9)+(l==9)); 28 //year(days in a year) 29 //+month(3*12,except February) 30 //+day(September) 31 if (s%4==0 && (s%100!=0 || s%400==0)) 32 ge[s]=366*g+36+30; 33 else 34 ge[s]=365*g+35+30; 35 } 36 //line[i]:the number of "9" in year 2000~i 37 line[1999]=0; 38 for (i=2000;i<=9999;i++) 39 line[i]=line[i-1]+ge[i]; 40 scanf("%ld",&t); 41 for (l=1;l<=t;l++) 42 { 43 scanf("%ld%ld%ld%ld%ld%ld",&y1,&m1,&d1,&y2,&m2,&d2); 44 //year [y1,y2) "[":included "(":not included 45 ans=line[y2-1]-line[y1-1]; 46 47 //1 delete y1.1.1~y1.m1.(d1-1) 48 g=(y1%10==9)+(y1/10%10==9)+(y1/100%10==9)+(y1/1000%10==9); 49 //judge if loop year or not 50 if (y1%4==0 && (y1%100!=0 || y1%400==0)) 51 run1=1; 52 else 53 run1=0; 54 //year(days in year y1) 55 if (run1==1) 56 ans-=g*tmonth_leap[m1-1]; 57 else 58 ans-=g*tmonth[m1-1]; 59 ans-=(d1-1)*g; 60 61 //month 62 ans-=(m1-1)*3; 63 if (d1>=30) 64 ans-=3; 65 else if (d1>=20) 66 ans-=2; 67 else if (d1>=10) 68 ans-=1; 69 //February 70 if (run1==0 && m1>2) 71 ans++; 72 //month 73 if (m1>9) 74 ans-=30; 75 else if (m1==9) 76 ans-=(d1-1); 77 78 //2 add y2.1.1~y2.m2.d2 79 g=(y2%10==9)+(y2/10%10==9)+(y2/100%10==9)+(y2/1000%10==9); 80 if (y2%4==0 && (y2%100!=0 || y2%400==0)) 81 run2=1; 82 else 83 run2=0; 84 if (run2==1) 85 ans+=g*tmonth_leap[m2-1]; 86 else 87 ans+=g*tmonth[m2-1]; 88 ans+=d2*g; 89 90 ans+=(m2-1)*3; 91 if (d2>=29) 92 ans+=3; 93 else if (d2>=19) 94 ans+=2; 95 else if (d2>=9) 96 ans+=1; 97 if (run2==0 && m2>2) 98 ans--; 99 100 if (m2>9) 101 ans+=30; 102 else if (m2==9) 103 ans+=d2; 104 105 printf("%ld\n",ans); 106 } 107 return 0; 108 }
感想:
正确题数机制:
1.认真看题,不要漏掉一些特殊情况。
2.多设数据,查看自己的程序是否完善。
3.对于渣渣,还是从简单题做起,不要对繁琐的模拟题丧失耐心,因为这是你得分的关键。
尤其是这道模拟题,细心加耐心
当你做出这道题提交上去时WrongAnswer,然后看了几遍自己程序,修改了一下,然后提交上去,还是WrongAnswer时,你的内心是崩溃的!
错误一般是:
1.漏掉一些特殊点
2.变量,下标写错
这时你可以这样做:
1.在网上找一份对的程序(亲自提交一下)
2.对自己的程序和标程创建文件流
(网上别人的程序)
1 #include <iostream> 2 #include <cstring> 3 #include <string> 4 #include <vector> 5 #include <queue> 6 #include <cstdio> 7 #include <set> 8 #include <math.h> 9 #include <algorithm> 10 #include <queue> 11 #include <iomanip> 12 #include <map> 13 #define INF 0x3f3f3f3f 14 #define MAXN 1005 15 #define Mod 99999999 16 using namespace std; 17 int num[10005]; 18 int count9(int n) 19 { 20 int cnt=0; 21 while(n!=0) 22 { 23 if(n%10==9) 24 cnt++; 25 n/=10; 26 } 27 return cnt; 28 } 29 bool isleap(int y) 30 { 31 if((y%4==0&&y%100!=0)||y%400==0) 32 return true; 33 return false; 34 } 35 void Init() 36 { 37 int sum=0; 38 for(int i=2000; i<=9999; ++i) 39 { 40 if(isleap(i)) 41 sum=count9(i)*366; 42 else 43 sum=count9(i)*365; 44 sum+=30; 45 sum+=11*3; 46 if(isleap(i)) 47 sum+=3; 48 else 49 sum+=2; 50 num[i]=sum; 51 } 52 } 53 int mon1[]= {0,31,28,31,30,31,30,31,31,30,31,30,31}; 54 int mon2[]= {0,31,29,31,30,31,30,31,31,30,31,30,31}; 55 int main() 56 { 57 FILE *in=fopen("C:\\Users\\Lenovo\\Desktop\\in.txt","r"); 58 FILE *out=fopen("C:\\Users\\Lenovo\\Desktop\\out_standard.txt","w"); 59 Init(); 60 int t; 61 //scanf("%d",&t); 62 fscanf(in,"%d",&t); 63 while(t--) 64 { 65 int y1,m1,d1,y2,m2,d2; 66 int ans=0; 67 //scanf("%d%d%d%d%d%d",&y1,&m1,&d1,&y2,&m2,&d2); 68 fscanf(in,"%d%d%d%d%d%d",&y1,&m1,&d1,&y2,&m2,&d2); 69 if(y1==y2) 70 { 71 int days=0; 72 for(int i=m1+1; i<m2; ++i) 73 { 74 if(i==2&&isleap(y1)) 75 ans+=3; 76 else if(i==2&&!isleap(y1)) 77 ans+=2; 78 else if(i==9) 79 ans+=33; 80 else 81 ans+=3; 82 if(!isleap(y1)) 83 days+=mon1[i]; 84 else 85 days+=mon2[i]; 86 } 87 if(m1==m2) 88 { 89 for(int i=d1; i<=d2; ++i) 90 { 91 ans+=count9(i); 92 days++; 93 if(m1==9) 94 ans++; 95 } 96 ans=ans+days*count9(y1); 97 //printf("%d\n",ans); 98 fprintf(out,"%d\n",ans); 99 } 100 else 101 { 102 if(!isleap(y1)) 103 { 104 for(int i=d1; i<=mon1[m1]; ++i) 105 { 106 ans+=count9(i); 107 days++; 108 if(m1==9) 109 ans++; 110 } 111 } 112 else 113 { 114 for(int i=d1; i<=mon2[m1]; ++i) 115 { 116 ans+=count9(i); 117 days++; 118 if(m1==9) 119 ans++; 120 } 121 } 122 for(int i=1; i<=d2; ++i) 123 { 124 ans+=count9(i); 125 days++; 126 if(m2==9) 127 ans++; 128 } 129 ans=ans+days*count9(y1); 130 //printf("%d\n",ans); 131 fprintf(out,"%d\n",ans); 132 } 133 } 134 else 135 { 136 for(int i=y1+1; i<y2; ++i) 137 ans+=num[i]; 138 int days1=0,days2=0; 139 for(int i=m1+1; i<=12; ++i) 140 { 141 if(i==2&&isleap(y1)) 142 ans+=3; 143 else if(i==2&&!isleap(y1)) 144 ans+=2; 145 else if(i==9) 146 ans+=33; 147 else 148 ans+=3; 149 if(!isleap(y1)) 150 days1+=mon1[i]; 151 else 152 days1+=mon2[i]; 153 } 154 if(!isleap(y1)) 155 { 156 for(int i=d1; i<=mon1[m1]; ++i) 157 { 158 ans+=count9(i); 159 days1++; 160 if(m1==9) 161 ans++; 162 } 163 } 164 else 165 { 166 for(int i=d1; i<=mon2[m1]; ++i) 167 { 168 ans+=count9(i); 169 days1++; 170 if(m1==9) 171 ans++; 172 } 173 } 174 ans=ans+days1*count9(y1); 175 176 for(int i=1; i<m2; ++i) 177 { 178 if(i==2&&isleap(y2)) 179 ans+=3; 180 else if(i==2&&!isleap(y2)) 181 ans+=2; 182 else if(i==9) 183 ans+=33; 184 else 185 ans+=3; 186 if(!isleap(y2)) 187 days2+=mon1[i]; 188 else 189 days2+=mon2[i]; 190 } 191 for(int i=1; i<=d2; ++i) 192 { 193 ans+=count9(i); 194 days2++; 195 if(m2==9) 196 ans++; 197 } 198 ans=ans+days2*count9(y2); 199 //printf("%d\n",ans); 200 fprintf(out,"%d\n",ans); 201 } 202 } 203 204 fclose(in); 205 fclose(out); 206 return 0; 207 }
自己的程序(目前是错的):
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main() 5 { 6 FILE *in=fopen("C:\\Users\\Lenovo\\Desktop\\in.txt","r"); 7 FILE *out=fopen("C:\\Users\\Lenovo\\Desktop\\out.txt","w"); 8 long month[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}; 9 long month_leap[13]={0,31,29,31,30,31,30,31,31,30,31,30,31}; 10 long tmonth[13],tmonth_leap[13]; 11 long t,i,j,k,l,s,g,y1,m1,d1,y2,m2,d2,run1,run2,ans=0; 12 long ge[10000]={0},line[10000]; 13 tmonth[0]=0; 14 tmonth_leap[0]=0; 15 for (i=1;i<12;i++) 16 { 17 tmonth[i]=tmonth[i-1]+month[i]; 18 tmonth_leap[i]=tmonth_leap[i-1]+month_leap[i]; 19 } 20 //2000-01-01 and 9999-12-31 21 for (i=2;i<=9;i++) 22 for (j=0;j<=9;j++) 23 for (k=0;k<=9;k++) 24 for (l=0;l<=9;l++) 25 { 26 s=i*1000+j*100+k*10+l; 27 g=((i==9)+(j==9)+(k==9)+(l==9)); 28 if (s%4==0 && (s%100!=0 || s%400==0)) 29 ge[s]=366*g+36+30; 30 else 31 ge[s]=365*g+35+30; 32 } 33 line[1999]=0; 34 for (i=2000;i<=9999;i++) 35 line[i]=line[i-1]+ge[i]; 36 //scanf("%ld",&t); 37 fscanf(in,"%ld",&t); 38 for (l=1;l<=t;l++) 39 { 40 //scanf("%ld%ld%ld%ld%ld%ld",&y1,&m1,&d1,&y2,&m2,&d2); 41 fscanf(in,"%ld%ld%ld%ld%ld%ld",&y1,&m1,&d1,&y2,&m2,&d2); 42 ans=line[y2-1]-line[y1-1]; 43 44 g=(y1%10==9)+(y1/10%10==9)+(y1/100%10==9)+(y1/1000%10==9); 45 if (y1%4==0 && (y1%100!=0 || y1%400==0)) 46 run1=1; 47 else 48 run1=0; 49 if (run1==1) 50 ans-=g*tmonth_leap[m1-1]; 51 else 52 ans-=g*tmonth[m1-1]; 53 ans-=(d1-1)*g; 54 55 ans-=(m1-1)*3; 56 if (d1>=30) 57 ans-=3; 58 else if (d1>=20) 59 ans-=2; 60 else if (d1>=10) 61 ans-=1; 62 if (run1==0 && m1>2) 63 ans++; 64 65 if (m1>9) 66 ans-=30; 67 else if (m1==9) 68 ans-=(d1-1); 69 70 71 g=(y2%10==9)+(y2/10%10==9)+(y2/100%10==9)+(y2/1000%10==9); 72 if (y2%4==0 && (y2%100!=0 || y2%400==0)) 73 run2=1; 74 else 75 run2=0; 76 if (run2==1) 77 ans+=g*tmonth_leap[m2-1]; 78 else 79 ans+=g*tmonth[m2-1]; 80 ans+=d2*g; 81 82 ans+=(m2-1)*3; 83 if (d2>=29) 84 ans+=3; 85 else if (d2>=19) 86 ans+=2; 87 else if (d2>=9) 88 ans+=1; 89 if (run2==0 && m2>2) 90 ans--; 91 92 if (m2>9) 93 ans+=30; 94 else if (m2==9) 95 ans+=d1; 96 97 //printf("%ld\n",ans); 98 fprintf(out,"%ld\n",ans); 99 } 100 101 fclose(in); 102 fclose(out); 103 return 0; 104 } 105 /* 106 9999 1 19 9999 12 21 107 */
3.创建数据:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <time.h> 4 #define num 100 5 6 int main() 7 { 8 FILE *out=fopen("C:\\Users\\Lenovo\\Desktop\\in.txt","w"); 9 long month[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}; 10 long month_leap[13]={0,31,29,31,30,31,30,31,31,30,31,30,31}; 11 long y1,m1,d1,y2,m2,d2,i,t; 12 srand(time(NULL)); 13 fprintf(out,"%ld\n",num); 14 for (i=1;i<=num;i++) 15 { 16 y1=2000+rand()%8000; 17 y2=2000+rand()%8000; 18 if (y1>y2) 19 { 20 t=y1; 21 y1=y2; 22 y2=t; 23 } 24 m1=rand()%12+1; 25 m2=rand()%12+1; 26 if (y1==y2 && m1>m2) 27 { 28 t=m1; 29 m1=m2; 30 m2=t; 31 } 32 if (y1%4==0 && (y1%100!=0 || y1%400==0)) 33 d1=rand()%month_leap[m1]+1; 34 else 35 d1=rand()%month[m1]+1; 36 if (y2%4==0 && (y2%200!=0 || y2%400==0)) 37 d2=rand()%month_leap[m2]+1; 38 else 39 d2=rand()%month[m2]+1; 40 if (y1==y2 && m1==y2 && d1>d2) 41 { 42 t=d1; 43 d1=d2; 44 d2=t; 45 } 46 fprintf(out,"%ld %ld %ld %ld %ld %ld\n",y1,m1,d1,y2,m2,d2); 47 } 48 fclose(out); 49 system("C:\\Users\\Lenovo\\Desktop\\test_c\\bin\\Debug\\test_c.exe"); 50 system("C:\\Users\\Lenovo\\Desktop\\The_17th_Zhejiang_University_Programming_Contest_Sponsored_by_TuSimple\\c_sumbit\\bin\\Debug\\c_sumbit.exe"); 51 system("C:\\Users\\Lenovo\\Desktop\\Judge_Correct\\bin\\Debug\\Judge_Correct.exe"); 52 53 return 0; 54 }
4.判断对错程序(自己程序与标准程序输出的区别,具体到哪一行是错的):
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main() 5 { 6 FILE *in1=fopen("C:\\Users\\Lenovo\\Desktop\\out.txt","r"); 7 FILE *in2=fopen("C:\\Users\\Lenovo\\Desktop\\out_standard.txt","r"); 8 9 long x,y,ans=0; 10 11 while (fscanf(in1,"%ld",&x)!=EOF && fscanf(in2,"%ld",&y)!=EOF) 12 { 13 ans++; 14 if (x!=y) 15 { 16 printf("Line %ld !",ans); 17 printf("Wrong\n"); 18 fclose(in1); 19 fclose(in2); 20 return 0; 21 } 22 } 23 if (fscanf(in1,"%ld",&x)!=EOF || fscanf(in2,"%ld",&y)!=EOF) 24 { 25 printf("Wrong\n"); 26 fclose(in1); 27 fclose(in2); 28 return 0; 29 } 30 printf("Correct\n"); 31 fclose(in1); 32 fclose(in2); 33 return 0; 34 }
5.执行程序,查看自己程序的错误
Output(etc):
Line 5 !
Wrong
6.查看错误的答案所对应的数据有什么共通的地方(那个地方就是你错误所在的地方),修改程序,直到自己程序是对的(多运行几次,因为数据是随机生成的)。
建议:
1.像这种模拟题提交前自己重新过一遍自己的程序,多设置几个特殊(特殊情况)和普遍(多种多样)的测试点。
2.平时做题注意收藏题目数据和官方解题报告,做一道题真正的收获是发现不足(没测试数据会让你卡在同一个地方)和学习新知识和方法(别人的解题过程)。