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)%1000,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; } }