pat链接:
http://pat.zju.edu.cn
1001
1 #include<stdio.h> 2 int main(){ 3 int a,b; 4 int c; 5 while (scanf( " %d %d " ,&a,&b)!= EOF){ 6 c=a+ b; 7 if (c< 0 ){ 8 c=- c; 9 printf( " - " ); 10 } 11 if (c>= 1000000 ) 12 printf( " %d,%03d,%03d\n " ,c/ 1000000 ,(c/ 1000 )%10 00 ,c%1000); 13 else if (c>= 1000 ) 14 printf( " %d,%03d\n " ,c/ 1000 ,c%1000); 15 else 16 printf( " %d\n " ,c); 17 } 18 return 0 ; 19 }
关键是代码的长度有限制所以简化了整个程序
1 #include<stdio.h> 2 int main(){ 3 int k1,k2; 4 int m[ 10 ],n[ 10 ]; 5 double a[ 10 ],b[ 10 ],c[ 10 ]; 6 int i,count; 7 memset(m, 0 , sizeof (m)); 8 memset(n, 0 , sizeof (m)); 9 memset(a, 0 , sizeof (a)); 10 memset(b, 0 , sizeof (a)); 11 memset(c, 0 , sizeof (a)); 12 scanf( " %d " ,& k1); 13 for (i= 0 ;i<k1;i++ ){ 14 scanf( " %d " ,& m[i]); 15 scanf( " %lf " ,& a[m[i]]); 16 } 17 scanf( " %d " ,& k2); 18 for (i= 0 ;i<k2;i++ ){ 19 scanf( " %d " ,& n[i]); 20 scanf( " %lf " ,& b[n[i]]); 21 } 22 count= 0 ; 23 for (i= 0 ;i<=(k1>k2?k1:k2);i++ ){ 24 c[i]=a[i]+ b[i]; 25 if (c[i]!= 0 ) 26 count++ ; 27 } 28 printf( " %d " ,count); 29 for (i=count;i>= 0 ;i-- ){ 30 if (c[i]!= 0 &&i!= 0 ){ 31 printf( " %d %.1f " ,i,c[i]); 32 } 33 else if (c[i]!= 0 &&i== 0 ) 34 printf( " %d %.1f\n " ,i,c[i]); 35 } 36 return 0 ; 37 }
AC代码:
1 #include<stdio.h> 2 #include< string .h> 3 using namespace std; 4 5 double a[ 1002 ]; 6 double b[ 1002 ]; 7 8 int main( void ){ 9 int n,i,temp; 10 memset(a, 0 , sizeof (a)); 11 memset(b, 0 , sizeof (b)); 12 scanf( " %d " ,& n); 13 for (i= 0 ;i<n;i++ ){ 14 scanf( " %d " ,& temp); 15 scanf( " %lf " ,& a[temp]); 16 } 17 scanf( " %d " ,& n); 18 for (i= 0 ;i<n;i++ ){ 19 scanf( " %d " ,& temp); 20 scanf( " %lf " ,& b[temp]); 21 } 22 int count = 0 ; 23 for (i= 0 ;i< 1002 ;i++ ){ 24 a[i]+= b[i]; 25 if (a[i]!= 0 ) count++ ; 26 } 27 printf( " %d " ,count); 28 for (i= 1001 ;i>= 0 ;i-- ) 29 if (a[i]!= 0 ){ 30 count-- ; 31 printf(count== 0 ? " %d %.1f\n " : " %d %.1f " ,i,a[i]); 32 } 33 return 0 ; 34 }
因为最大只有1000,所以完全可以利用空间来简化程序,建立容量为1000的数组,然后从1到1000开始遍历(其实好笨的方法)注意memeset的用法,初始化太重要,c语言没初始化各种弊病
1003:(重要!!)
1 #include<stdio.h> 2 #include< string .h> 3 int map[ 501 ][ 501 ]; 4 int dis[ 501 ]; 5 bool mark[ 501 ]; 6 int team[ 501 ]; 7 int maxteam[ 501 ]; 8 int pathnum[ 501 ]; 9 const int max= 123123123 ; 10 int n,m,c1,c2; 11 void dij(){ 12 int i,j; 13 int k; 14 dis[c1]= 0 ; 15 // mark[c1]=1; 16 pathnum[c1]= 1 ; 17 maxteam[c1]= team[c1]; 18 19 for (i= 0 ;i<n;i++ ){ 20 int min= max; 21 for (j= 0 ;j<n;j++ ){ 22 if (dis[j]<min&&! mark[j]){ 23 min= dis[j]; 24 k= j; 25 } 26 } 27 if (k==c2) return ; // 因为终点已经固定,已经找到直接返回 28 mark[k]= 1 ; 29 for (j= 0 ;j<n;j++ ){ 30 if (mark[j]== 0 ){ 31 if (dis[k]+map[k][j]< dis[j]){ 32 dis[j]=dis[k]+ map[k][j]; 33 pathnum[j]= pathnum[k]; 34 maxteam[j]=maxteam[k]+ team[j]; 35 } 36 else if (dis[k]+map[k][j]== dis[j]){ 37 pathnum[j]+= pathnum[k]; 38 if (maxteam[k]+team[j]> maxteam[j]){ 39 maxteam[j]=maxteam[k]+ team[j]; 40 } 41 } 42 } 43 } 44 } 45 } 46 int main(){ 47 int i,j; 48 int a,b; 49 freopen( " in.txt " , " r " ,stdin); 50 51 scanf( " %d%d%d%d " ,&n,&m,&c1,& c2); 52 for (i= 0 ;i<n;i++ ){ 53 dis[i] = max; 54 mark[i] = 0 ; 55 // maxteam[i] = 0; 56 // pathcount[i] = 0; 57 team[i]= 0 ; 58 for (j= 0 ;j<n;j++ ) 59 map[i][j]=map[j][i] = max; 60 } 61 for (i= 0 ;i<n;i++ ) 62 scanf( " %d " ,& team[i]); 63 for (i= 0 ;i<m;i++ ){ 64 scanf( " %d%d " ,&a,& b); 65 scanf( " %d " ,& map[a][b]); 66 map[b][a]=map[a][b]; // end of input 67 } 68 dij(); 69 70 printf( " %d %d\n " ,pathnum[c2],maxteam[c2]); 71 return 0 ; 72 }
一直没解决的一个难题,只是因为涉及到最短路径算法,不熟悉就一直空着没做,终于还是做了。
这是标准的一个使用邻接矩阵的dijkstra算法的最短路径题目。看资料看了好久才明白了实现的思路,一定要记住这个思路,写出来的代码基本是差不多的:
1 #include<stdio.h> 2 #include< string .h> 3 char eng[ 10 ][ 10 ]= { 4 " zero " , 5 " one " , 6 " two " , 7 " three " , 8 " four " , 9 " five " , 10 " six " , 11 " seven " , 12 " eight " , 13 " nine " 14 }; 15 int main(){ 16 char snum[ 10000 ],rnum[ 100 ]; 17 int i; 18 long r; 19 int count; 20 scanf( " %s " ,snum); 21 r= 0 ; 22 for (i= 0 ;i<strlen(snum);i++ ){ 23 r+=snum[i]- 48 ; 24 } 25 sprintf(rnum, " %d " ,r); 26 for (i= 0 ;i<strlen(rnum);i++ ){ 27 count=rnum[i]- 48 ; 28 if (i==strlen(rnum)- 1 ) 29 printf( " %s " ,eng[count]); 30 else 31 printf( " %s " ,eng[count]); 32 } 33 }
一遍AC!!感觉还是很爽的有木有!!关键是用好全局的数组来进行转换,利用好字符串和数字的转换!例如i=c-48;利用码来进行单个数字字符的转换,以及sprintf(char,"%d",int);进行整个数字转字符串。
1 #include<stdio.h> 2 #include< string .h> 3 struct PERSON{ 4 char id[ 20 ]; 5 char intime[ 10 ]; 6 char outime[ 10 ]; 7 8 }p[ 200 ]; 9 int main(){ 10 int i,n; 11 int first,last; 12 scanf( " %d " ,& n); 13 for (i= 0 ;i<n;i++ ){ 14 scanf( " %s %s %s " ,p[i].id,p[i].intime,p[i].outime); 15 } 16 first= 0 ; 17 for (i= 1 ;i<n;i++ ){ 18 if (strcmp(p[i].intime,p[first].intime)< 0 ) 19 first= i; 20 } 21 last= 0 ; 22 for (i= 1 ;i<n;i++ ){ 23 if (strcmp(p[i].outime,p[last].outime)> 0 ) 24 last= i; 25 } 26 printf( " %s %s " ,p[first].id,p[last].id); 27 return 0 ; 28 }
还是挺简单的,一会就AC了,出了小问题是结构数组不够大,加大了就OK了。
1007:
1 #include<stdio.h> 2 #include< string .h> 3 int a[ 10000 ]; 4 int main(){ 5 int i,k; 6 int sum= 0 ,start= 0 ,end= 0 ,max= 0 ,rs= 0 ; 7 int flag= 0 ; 8 memset(a, 0 , sizeof (a)); 9 scanf( " %d " ,& k); 10 for (i= 0 ;i<k;i++ ){ 11 scanf( " %d " ,& a[i]); 12 if (a[i]> 0 ) flag= 1 ; 13 sum+= a[i]; 14 if (sum> max){ 15 max= sum; 16 end= i; 17 rs= start; 18 } 19 if (sum< 0 ){ 20 sum= 0 ; 21 start=i+ 1 ; 22 } 23 } 24 if (flag== 0 ) 25 printf( " 0 %d %d " ,a[ 0 ],a[k- 1 ]); 26 else 27 printf( " %d %d %d " ,max,a[rs],a[end]); 28 return 0 ; 29 }
动态规划最典型的一道题,也是入门级别的一道题。自己对动态规划理解还不够深刻,这是通过阅读别人的代码后自己再改写的。整个过程差不多理解了这道题的思想。其实不复杂,就是两种情况,sum大于max的话,把值赋给max,将当前的次序号当做end,重新记录一个rs来确定本段的起始;一旦sum<0,则前边的都舍弃不要,将start定为下一个。懂了基本思想就好些了。但是有一组过不去,不知道什么原因。。。
1008:
1 #include<stdio.h> 2 #include< string .h> 3 int main(){ 4 int i,n,s; 5 int a[ 105 ]; 6 scanf( " %d " ,& n); 7 memset(a, 0 , sizeof (a)); 8 for (i= 0 ;i<n;i++ ) 9 scanf( " %d " ,& a[i]); 10 s=n* 5 ; 11 for (i= 1 ;i<n;i++ ){ 12 if (a[i]>a[i- 1 ]) 13 s+= 6 *(a[i]-a[i- 1 ]); 14 else 15 s+= 4 *(a[i- 1 ]- a[i]); 16 } 17 s+=a[ 0 ]* 6 ; 18 printf( " %d " ,s); 19 return 0 ; 20 }
太简单了,懒得说。
1009:
1 #include<stdio.h> 2 #include< string .h> 3 double a[ 1002 ]; 4 double b[ 1002 ]; 5 double c[ 2004 ]; 6 int main(){ 7 int i,j,n; 8 int k1,k2; 9 int count; 10 memset(a, 0 , sizeof (a)); 11 memset(b, 0 , sizeof (b)); 12 memset(c, 0 , sizeof (c)); 13 scanf( " %d " ,& k1); 14 for (i= 0 ;i<k1;i++ ){ 15 scanf( " %d " ,& n); 16 scanf( " %lf " ,& a[n]); 17 } 18 scanf( " %d " ,& k2); 19 for (i= 0 ;i<k2;i++ ){ 20 scanf( " %d " ,& n); 21 scanf( " %lf " ,& b[n]); 22 } 23 count= 0 ; 24 for (i= 0 ;i< 1001 ;i++ ){ 25 if (a[i]!= 0 ){ 26 for (j= 0 ;j< 1001 ;j++ ){ 27 if (b[j]!= 0 ){ 28 c[i+j]+=a[i]* b[j]; 29 } 30 } 31 } 32 } 33 for (i= 0 ;i< 2001 ;i++ ) 34 if (c[i]) 35 count++ ; 36 printf( " %d " ,count); 37 for (i= 2000 ;i>= 0 ;i-- ){ 38 if (c[i]) 39 printf( " %d %.1lf " ,i,c[i]); 40 } 41 printf( " \n " ); 42 return 0 ; 43 }
核心的算法其实就一句话:c[i+j]+=a[i]*b[j];这题和1002很相似。PS:把最后输出条件c[i]!=0改成c[i]就A过了,不然有几组死活通不过,这是什么问题。。以后记得注意这个问题,少用!=0的判断式
1010:
1 #include<stdio.h> 2 #include< string .h> 3 #include<math.h> 4 long long todec( char *n, int rad); 5 int main(){ 6 int tag,radt; 7 char n1[ 15 ],n2[ 15 ]; 8 long long int d1= 0 ,d2= 0 ; 9 long long i; 10 scanf( " %s %s %d %d " ,&n1,&n2,&tag,& radt); 11 if (tag== 1 ){ 12 d1= todec(n1,radt); 13 for (i= 1 ;;i++ ){ 14 if (d1== todec(n2,i)){ 15 printf( " %d " ,i); 16 break ; 17 } 18 else if (todec(n2,i)> d1){ 19 printf( " Impossible " ); 20 break ; 21 } 22 } 23 } 24 else { 25 d2= todec(n2,radt); 26 for (i= 1 ;;i++ ){ 27 if (d2== todec(n1,i)){ 28 printf( " %d " ,i); 29 break ; 30 } 31 else if (todec(n1,i)> d2){ 32 printf( " Impossible " ); 33 break ; 34 } 35 } 36 } 37 return 0 ; 38 } 39 long long todec( char *n, int rad){ 40 int i,l; 41 long d= 0 ; 42 if (rad!= 10 ){ 43 // sprintf(s1,"%d",n1); 44 l= strlen(n); 45 for (i= 0 ;i<l;i++ ){ 46 if (n[i]<= ' 9 ' &&n[i]>= ' 0 ' ) 47 d+=(n[i]- 48 )*pow(rad,l-i- 1 ); 48 else if (n[i]<= ' z ' &&n[i]>= ' a ' ) 49 d+=(n[i]- ' a ' + 10 )*pow(rad,l-i- 1 ); 50 } 51 } 52 else 53 sscanf(n, " %ld " ,&d); // 从n中读取%d格式的d1 54 return d; 55 56 }
最崩溃的一道题。。本来觉得很难,根本无法下手,其实想清楚也没那么难,关键是要把所有的数据都转换为10进制然后再比较。结果发现只能过一小部分。接着把int改成long long型,还是有的过不去。。貌似我理解的题意有问题。。有一组超大数据要用二分法才能过去,先这样了,有时间再写个二分法的算法吧,待续。。
看到一个二分法搜索的具体做法: http://blog.csdn.net/whosemario/article/details/8734508
1 #include <iostream> 2 #include < string .h> 3 using namespace std; 4 5 int equal( char * A, char * B){ 6 int i,j; 7 for ( int i= 0 ;i<strlen(A);i++) if (A[i]!= ' 0 ' ) break ; 8 for ( int j= 0 ;j<strlen(B);j++) if (B[j]!= ' 0 ' ) break ; 9 int lenA = strlen(A); 10 int lenB = strlen(B); 11 if (lenA-i != lenB-j) return - 1 ; 12 for ( int k= 0 ;k<lenA-i;k++ ) 13 if (A[lenA- 1 -k]!=B[lenB- 1 -k]) return false ; 14 if (lenA-i== 1 &&A[lenA- 1 ]== ' 1 ' ) return 1 ; 15 return 2 ; 16 } 17 18 long long str2Num( char * A, long long radix){ 19 int len = strlen(A); 20 long long ret = 0 ; 21 long long p = 1 ; 22 23 for ( int i=len- 1 ;i>= 0 ;i-- ){ 24 int num ; 25 if (A[i]>= ' 0 ' && A[i]<= ' 9 ' ) num = A[i]- ' 0 ' ; 26 else num = A[i]- ' a ' + 10 ; 27 ret += p* num; 28 p*= radix; 29 } 30 31 return ret; 32 } 33 34 long long calcRadix( char * B){ 35 long long ret = 0 ; 36 int len = strlen(B); 37 for ( int i= 0 ;i<len;i++ ){ 38 int num ; 39 if (B[i]>= ' 0 ' && B[i]<= ' 9 ' ) num = B[i]- ' 0 ' ; 40 else num = B[i]- ' a ' + 10 ; 41 if (num+ 1 >ret) ret=num+ 1 ; 42 } 43 return ret; 44 } 45 46 int compare( char * B, long long radix, long long target){ 47 int len = strlen(B); 48 long long ret = 0 ; 49 long long p = 1 ; 50 for ( int i=len- 1 ;i>= 0 ;i-- ){ 51 int num; 52 if (B[i]>= ' 0 ' && B[i]<= ' 9 ' ) num = B[i]- ' 0 ' ; 53 else num = B[i]- ' a ' + 10 ; 54 ret += p* num; 55 if (ret > target) return 1 ; 56 p*= radix; 57 } 58 if (ret > target) return 1 ; 59 else if (ret<target) return - 1 ; 60 else return 0 ; 61 } 62 63 long long binarySearch( char * B, long long low, long long high, long long target){ 64 long long mid; 65 while (low<= high){ 66 mid = (low+high)/ 2 ; 67 int res = compare(B,mid,target); 68 if (res > 0 ) 69 high = mid- 1 ; 70 else if (res< 0 ) 71 low = mid+ 1 ; 72 else return mid; 73 } 74 return - 1 ; 75 } 76 77 int main() { 78 char A[ 12 ]; 79 char B[ 12 ]; 80 int chose; 81 long long radix; 82 83 cin>>A>>B>>chose>> radix; 84 int eq = equal(A,B); 85 if (eq== 1 ) printf( " 2\n " ); 86 else if (eq== 2 ) printf( " %d\n " ,radix); 87 else { 88 if (chose== 1 ){ 89 long long target = str2Num(A,radix); 90 long long least = calcRadix(B); 91 long long most = (target)>(least)?(target):(least); // input : 11 b 1 10 92 long long res = binarySearch(B,least,most,target); 93 if (res==- 1 ) cout<< " Impossible " << endl; 94 else cout<<res<< endl; 95 } 96 else { 97 long long target = str2Num(B,radix); 98 long long least = calcRadix(A); 99 long long most = (target)>(least)? (target):(least); 100 long long res = binarySearch(A,least,most,target); 101 if (res==- 1 ) cout<< " Impossible " << endl; 102 else cout<<res<< endl; 103 } 104 } 105 return 0 ; 106 }
发现基本思想都不一样额。。最小的进制就是它的某位最大的数字,最大就是被比较的另一个变量的值,然后再进行二分法搜索。而我的算法是从0到最大暴力搜索。
1059
1 #include<stdio.h> 2 #include<math.h> 3 int isp( long l); 4 int main(){ 5 long int n,t,cnt; 6 long int i; 7 scanf( " %ld " ,& n); 8 t= n; 9 i= 2 ; 10 if (n== 1 || isp(n)){ 11 printf( " %d=%d " ,n,n); 12 return 0 ; 13 } 14 printf( " %ld= " ,n); 15 while (! isp(t)){ 16 if (isp(i)){ 17 cnt= 0 ; 18 if (t%i== 0 ){ 19 20 while (t%i== 0 ){ 21 t/= i; 22 cnt++ ; 23 } 24 if (cnt== 1 ) 25 printf( " %ld " ,i); 26 else 27 printf( " %d^%d " ,i,cnt); 28 29 if (t!= 1 ) 30 printf( " * " ); 31 32 i++ ; 33 } 34 else 35 i++ ; 36 } 37 else 38 i++ ; 39 } 40 printf( " %d " ,t); 41 return 0 ; 42 } 43 int isp( long l){ 44 long i= 2 ; 45 while (i<sqrt(l)+ 1 ){ 46 if (l== 2 ) 47 return 1 ; 48 if (l%i== 0 ){ 49 return 0 ; 50 } 51 if (i==l- 1 ) 52 return 1 ; 53 i++ ; 54 } 55 56 }
纠结了好久的一道题,终于还是过了。。首先是判断素数,可以用sqrt来简化复杂度。如果是素数则直接输出,如果不是则进入循环来寻找它的因数。之前最初我用两组数组来记录每一个因数和它的次方,实在是复杂多余,后来改成了直接算一个输出一个,明显简化了许多。还有要注意特殊情况的输出,素数直接输出自身即可。还有最重要的一点是:循环结束条件的判断。余数如果是素数即可结束循环,我的程序一直超时,就是没有利用这个循环结束条件。
PS:关于找出所有素数的解法,还有一个高效的方法:素数筛选法
void init(){ primgsize = 0 ; for ( int i= 2 ;i<= 10000 ;i++ ){ if (mark[i]== true ) continue ; prime[primesize ++]= i; for ( int j=i*i;j<= 10000 ;j+= i){ mark[j] = true ; } }