PAT-Advanced Level--到第三章第六节

A1042 shuffling machine

1.可以使用字符数组来建立编号和花色的关系,若当前牌号为x,则mp[(x-1)/13]即为这张拍的花色,而(x-1)%13+1即为这张牌的数字。
2.设置两个数组,start[],end[],分别放置执行操作前的排序和执行操作后的排序,在执行完一次后,再让end[]覆盖start[]以此进行下一次排序操作,这样执行完成后数组start[]保存的就是最终的牌序。
这是自己写的,写得很罗嗦,思考了很久才发现问题在于自己只定义了一个数组,这样会导致牌序出现重复,总之这样做时完全错误的,必须用另一个数组来保存执行操作后的结果!
–已通过OJ

#include <cstdio>

int main() {
	int k;
	scanf("%d", &k);
	int cards[55], cards_f[55]={0};
	for(int i=0; i<55; i++) {
		cards[i]=i;			//牌的初始顺序 
	}
	int order[55],temp;		//order表示输入的次序 
	int u=k;
	while(k--) {
		for(int i=1; i<55; i++) {
			if(u==k+1) scanf("%d", &order[i]);
			//printf("order=%d\t", order);
			cards_f[order[i]]=cards[i]; 
	}
		for(int i=1; i<55; i++) {
			cards[i]=cards_f[i];
		}
	}
	for(int i=1; i<55; i++) {
		if(cards[i]<=13) {
			printf("S%d", cards[i]);
		} else if(cards[i]<=26) {
			printf("H%d", cards[i]-13);
		} else if(cards[i]<=39) {
			printf("C%d", cards[i]-26);
		} else if(cards[i]<=52) {
			printf("D%d", cards[i]-39);
		} else {
			printf("J%d", cards[i]-52);
		}
		if(i<54) printf(" ");
	}
	
	return 0;
}

下面是书中的参考代码,非常简洁,

#include <cstdio>
const int N=54;
char mp[5] = {'S', 'H', 'C', 'D', 'J'};		//牌序与花色的对应关系 
int start[N+1], end[N+1], next[N+1];		//其中next[]用来保存执行操作的顺序 
int main() {
	int k;
	scanf("%d", &k);
	for(int i=1; i<=N; i++) {
		start[i]=i;				//初始时牌的编号 
	}
	for(int i=1; i<=N; i++) {
		scanf("%d", &next[i]);
	} 
	for(int step=0; step<k; step++) {
		for(int i=1; i<=N; i++) {
			end[next[i]]=start[i];
		}
		for(int i=1; i<=N; i++) {
			start[i]=end[i];
		}
	}
	for(int i=1; i<=N; i++) {
		if(i!=1) printf(" ");
		start[i]--;
		printf("%c%d", mp[start[i]/13], start[i]%13+1);
	}
	return 0;
} 

A1046 Shortest Distance

最后一组数据运行超时,书中说是由于给定的M、N值太大,每次循环都要遍历一遍数组,导致运行超时。
此外,书中直接使用了swap(a,b)函数及min(a,b),需要在程序开头添加头文件:

#include <algorithm>
using namespace std;

algorithm头文件中包含了大量的函数,添加头文件后即可直接使用,
有如下函数:https://www.cnblogs.com/lgxZJ/p/6377437.html

#include <cstdio>

int main() {
	int N;		//N为出口个数
	scanf("%d", &N);
	int dist[N+1]={0}, M;		//dist[]储存的是各出口之间的距离,M为输入的出口对数
	for(int i=1; i<=N; i++) {
		scanf("%d", &dist[i]);
	} 
	scanf("%d", &M);
	int a, b;					//a,b分别是每次输入的两个出口 
	for(int i=0; i<M; i++) {
		scanf("%d %d", &a, &b);
		int temp;
		if(a>b) {
			temp=a;a=b;b=temp;
		} else if(a==b) {
			printf("0\n");break;
		} 
		int min_1=0, min_2=0;		//min_1表示a-b的直接距离,min_2表示b-5->a的距离 
		for(int j=a; j<b; j++) {	//计算min_1 
			min_1 += dist[j];
		} 
		for(int k=1; k<=N; k++) {	//计算min_2 
			if(k<a || k>=b) {
				min_2 += dist[k];
			}
		}
		int min=min_1>min_2?min_2:min_1;
		printf("%d", min);
		if(i<M-1) printf("\n");
	}
	
	return 0;
} 

修改后如下:
主要修改内容是把大循环内的访问dist[]数组的循环放在了外面,这样就不会导致运行超时!为了将这两个循环拿到大循环外面,因此新创立了一个数组dis_sum[],这个数组表示1号节点到i+1号节点顺时针的距离,这样在循环内部就可以直接调用这个数组dis_sum[b-1]-dsi[a-1]来计算出a到b的顺时针距离。
–已通过OJ

#include <cstdio>

int main() {
	int N;		//N为出口个数
	scanf("%d", &N);
	int dist[N+1]={0}, M, sum=0, dis_sum[N+1]={0};		//dist[]储存的是各出口之间的距离,M为输入的出口对数
	for(int i=1; i<=N; i++) {
		scanf("%d", &dist[i]);
		sum += dist[i];
		dis_sum[i]=sum;
		
	} 
	scanf("%d", &M);
	int a, b;					//a,b分别是每次输入的两个出口 
	for(int i=0; i<M; i++) {
		scanf("%d %d", &a, &b);
		int temp;
		if(a>b) {
			temp=a;a=b;b=temp;
		} else if(a==b) {
			printf("0\n");break;
		} 
		int min_1, min_2;		//min_1表示a-b的直接距离,min_2表示b-5->a的距离 
		min_1=dis_sum[b-1]-dis_sum[a-1]; 
		min_2=sum-min_1;			//计算min_2 
		int min=min_1>min_2?min_2:min_1;
		printf("%d", min);
		if(i<M-1) printf("\n");
	}
	
	return 0;
} 

A1065 A+B and C

问题:1.题目给定的ABC数据类型都超过了long long的数据类型能表达的范围,大于263 -1,且二者相加后更有可能出现溢出(溢出是指两个正数相加为负数或两个负数相加为正数),结果导致只通过了一个数据点。
2.关于各数据类型的字节数、范围:
对于64位编译器:
char-------1字节,范围是-128~127, 即-27 ~27 -1
short int --2字节,范围是-32768~32767, 即-215 ~215 -1
int----------4字节,范围是-2147483648~+2147483647,即-231 ~231 -1,109 以内都可以使用int
long long–8字节, 范围是-263 ~263 -1, 大约在1010 ~1018之间
unsigned long long–8字节,范围是0~264 -1
对于本题中的long long, 溢出的最小负数是-263 (由263对应),最大负数是-2(由264 -2对应),即可以知道,如果a+b>=263 ,则a+b>c,那么当a>0,b>0,a+b<0时必然有a+b>c,为true;
当a+b<-263 时,显然有a+b<c, 此时也会出现溢出,从263 (-263-1)到0(-264 ),因此当a<0,b<0,a+b>=0时有a+b<c,为false。

代码如下:

#include <cstdio>

int main() {
	long long A, B, C;
	int T;
	scanf("%d", &T);
	for(int i=1; i<=T; i++) {
		scanf("%lld%lld%lld", &A, &B, &C);
		if(A+B>C){
			printf("Case #%d: true", i);
		} else {
			printf("Case #%d: false", i);
		}
		if(i<T) printf("\n");
	}
	
	return 0;
}

修改后如下:
已通过OJ

#include <cstdio>

int main() {
	long long A, B, C;
	int T;
	scanf("%d", &T);
	for(int i=1; i<=T; i++) {
		scanf("%lld%lld%lld", &A, &B, &C);
		bool flag;
		long long res=A+B;
		if(A>0 && B>0 &&res<0) flag=true;		//正溢出情况
		else if(A<0 && B<0 && res>=0) flag =false;	//负溢出情况
		else if(res>C) flag=true;
		else flag=false; 
		if(flag){
			printf("Case #%d: true", i);
		} else {
			printf("Case #%d: false", i);
		}
		if(i<T) printf("\n");
	}
	
	return 0;
}

A1002 A+B for Polynomials

只有两个数据点通过了。。。

#include <cstdio>

int main() {
	double exp[1010]={0.0};		//保存指数i对应的系数 
	double a;					//a为系数 
	int i;						//i为指数 
	int n;						//每行多项式的对数 
	int count=0;
	for(int i=0; i<2; i++) {
		scanf("%d", &n);
		for(int j=0; j<n; j++){
			scanf("%d%lf", &i, &a);
			exp[i] += a;
		}
	} 
	//printf("a[0]=%.1f\n", exp[0]);
	int flag=1;
	for(int i=0; i<=1000; i++) {
		if(exp[i]>=1e-6 || exp[i]<=-1e-6) {
			count ++;
		}
	}
	printf("%d ", count);
	for(int i=1000; i>=0; i--) {
		if(exp[i]>=1e-6||exp[i]<=-1e-6) {
			if(flag==1) {
				printf("%d %.1f", i, exp[i]);
				flag=0;
			} else {
				printf(" %d %.1f", i, exp[i]);
			}
		}
	}
	return 0;
}

问题:1.第一个循环内的指数写成了与循环变量相同的字母!服了,我好蠢。

#include <cstdio>

int main() {
	double exp[1010]={};		//保存指数i对应的系数 
	double a;					//a为系数 
	int k;						//k为指数 
	int n;						//每行多项式的对数 
	int count=0;
	for(int i=0; i<2; i++) {
		scanf("%d", &n);
		for(int j=0; j<n; j++){
			scanf("%d%lf", &k, &a);
			exp[k] += a;
		}
	} 
	//printf("a[0]=%.1f\n", exp[0]);
	for(int i=0; i<=1000; i++) {
		if(exp[i]!=0) {
			count ++;
		}
	}
	printf("%d", count);
	for(int i=1000; i>=0; i--) {
		if(exp[i]!=0) {
			printf(" %d %.1f", i, exp[i]);
		}
	}
	return 0;
}

A1009 Product of Polynomials

已通过OJ

#include <cstdio>
const int maxsize=2010; 

int main() {
	int k;		//每行多项式对数
	double a1[maxsize+1]={0}, a2[maxsize+1]={0};
	//其中ai保存第一行读取的多项式,a2保存第二行每项和第一行相乘后的结果
	scanf("%d", &k);
	int exp;
	double coe;
	for(int i=0; i<k; i++) {
		scanf("%d%lf", &exp, &coe);
		a1[exp]=coe;
	} 
	scanf("%d", &k);
	for(int i=0; i<k; i++) {
		scanf("%d%lf", &exp, &coe);
		for(int j=0; j<maxsize; j++) {
			if(a1[j]!=0) {
				a2[j+exp]=a2[j+exp]+coe*a1[j];
			}	 
		}
	}
	int count=0;		//计数不为零的项 
	for(int i=0; i<maxsize; i++) {
		if(a2[i]!=0) {
			count++;
		}
	}
	printf("%d", count);
	for(int i=maxsize; i>=0; i--) {
		if(a2[i]!=0) {
			printf(" %d %.1f", i, a2[i]);
		}
	} 
	return 0;
} 

A1011 World Cup Betting

#include <cstdio>

int main() {
	char sub[3]={'W', 'T', 'L'}; //最后输出时调用的字符数组 
	double odds[3][3];			//保存概率的二维数组 
	
	for(int i=0; i<3; i++) {	//读入数据 
		for(int j=0; j<3; j++) {
			scanf("%lf", &odds[i][j]);
		}
	}
	
	int seq[3];					//保存最大概率对应的序号,对应着WTL 
	double max_odd[3]={0}; 			//保存每行最大概率 
	for(int i=0; i<3; i++) {
		for(int j=0; j<3; j++) {
			if(odds[i][j]>max_odd[i]) {
				max_odd[i]=odds[i][j];
				seq[i]=j;
			}
		}
	}
	double profit;
	profit=(max_odd[0]*max_odd[1]*max_odd[2]*0.65-1)*2;
	for(int i=0; i<3; i++) {
		printf("%c ", sub[seq[i]]);
	}
	printf("%.2f", profit);
	return 0;
}

A1006 Sign In and Sign Out

此题和B1028类似,基本思路是一样的

#include <cstdio>
struct sign_in_out{
	char id[16];
};

int main() {
	int m;		//m表示输入的学生信息个数
	scanf("%d", &m);
	sign_in_out info[m]; 
	int min_unlock=23*60*60+59*60+59;
	int max_lock=0;
	int min_num, max_num;		//表示最小和最大的total对应的位序 
	for(int i=0; i<m; i++) {
		int hh_in,mm_in,ss_in;
		int hh_out,mm_out, ss_out;
		int total_in, total_out;				//表示时分秒之和 
		scanf("%s%d:%d:%d", &info[i].id, &hh_in, &mm_in, &ss_in);
		scanf("%d:%d:%d", &hh_out, &mm_out, &ss_out);
		total_in=hh_in*3600+mm_in*60+ss_in;
		total_out=hh_out*3600+mm_out*60+ss_out;
		if(total_in<=min_unlock){
			min_unlock=total_in;
			min_num=i;
		} 
		if(total_out>=max_lock){
			max_lock=total_out;
			max_num=i;
		}
	}
	printf("%s %s", info[min_num].id, info[max_num].id);
	
	return 0;
}

对于头文件:
1.#include :C++的输入输出是由iostream标准库提供的,iostream库定义了以下三个标准流对象:
①cin,表示标准输入(standard input)的istream类对象。cin使我们可以从设备读入数据。
②cout,表示标准输出(standard output)的ostream类对象。cout使我们可以向设备输出或者写数据。
3)cerr,表示标准错误(standard error)的osttream类对象。cerr是导出程序错误消息的地方,它只能允许向屏幕设备写数据。
输出主要由重载的左移操作符(<<)来完成,输入主要由重载的右移操作符(>>)完成:

a表示将数据放入a对象中。
<<a表示将a对象中存储的数据拿出。

2.#include
3.using namespcae std:

后缀为.h的头文件C++标注已经明确提出不支持了。早些的实现将标准库功能定义在全局空间里,声明在带.h后缀的头文件里,C++标准为了和C区别开,也为了正确地使用命名空间,规定头文件不使用后缀.h。因此,当使用<iostream.h>时,相当于在C中调用库函数,使用的是全局命名空间,也就是早期的C++实现。当使用时,该头文件没有定义全局命名空间,必须使用namespace std,这样才能使用类似于cout这样的C++标识符。
namespace是指标识符的各种可见范围。
作者:PG-aholic
来源:CSDN
原文:https://blog.csdn.net/fsz520w/article/details/82561795
版权声明:本文为博主原创文章,转载请附上博文链接!

书中算法如下:

#include <cstdio>
#include <iostream>
using namespace std;
struct pnode{
	char id[20];
	int hh,mm,ss;
}temp,ans1,ans2;

bool great(pnode node1, pnode node2) {		//node1时间大于node2时间返回true 
	if(node1.hh!=node2.hh) return node1.hh>=node2.hh;
	if(node1.mm!=node2.mm) return node1.mm>=node2.mm;
	return node1.ss>=node2.ss;
}

int main() {
	int n;
	scanf("%d", &n);
	ans1.hh=24, ans1.mm=60, ans1.ss=60;
	ans2.hh=0, ans2.mm=0, ans2.ss=0;
	for(int i=0; i<n; i++) {
		//先读入签到时间
		scanf("%s %d:%d:%d", &temp.id, &temp.hh, &temp.mm, &temp.ss);
		if(great(temp,ans1)==false) {
			ans1=temp;
		}
		//读入签离时间
		scanf("%d:%d:%d", &temp.hh, &temp.mm,&temp.ss);
		if(great(temp, ans2)==true) ans2=temp; 
	}
	printf("%s %s", ans1.id, ans2.id);
}

A1036 Boys vs Girls

已通过OJ

#include <cstdio>
#include <iostream>
using namespace std;
struct student{
	char name[11];
	char gender;
	char id[11];
	int grade;
}temp,ans_f,ans_m;

int main() {
	int m;			//m表示输入学生的个数 
	scanf("%d", &m);
	ans_f.grade=0, ans_m.grade=100;
	int count_f=0, count_m=0;	//计数输入男女学生个数 
	for(int i=0; i<m; i++) {
		scanf("%s %c %s %d", &temp.name, &temp.gender, &temp.id, &temp.grade);
		if(temp.gender=='F'&&temp.grade>=ans_f.grade) {
			ans_f=temp;
			count_f++;
		}
		if(temp.gender=='M'&&temp.grade<=ans_m.grade) {
			ans_m=temp;
			count_m++;
		}
	}
	if(count_f!=0) {
		printf("%s %s\n", ans_f.name, ans_f.id);
	} else{
		printf("Absent\n");
	}
	if(count_m!=0) {
		printf("%s %s\n", ans_m.name, ans_m.id);
	} else {
		printf("Absent\n");
	}
	if(count_f!=0&&count_m!=0) {
		printf("%d", ans_f.grade-ans_m.grade);
	}else {
		printf("NA");
	}
	
	
	return 0;
}

值得注意的是,书中在赋值给ans_f.grade和ans_m.grade时分别赋了-1和101,这样在后面输出特殊情况的时候就不用单独定义count_f和count_m了,更加简洁。

A1031 Hello World For U

1.两个测试点显示格式错误
发现是由于计算n1,n2,n3的公式不对,迷,每次找规律都不会找,我好蠢。
n1,n3是(N+2)/3向下取整,
n2由公式计算得到,n2=n+2-n1-n3
,修改之后即可通过OJ
2.书中是用二维数组输出的,
题目中给定的n1,n3的限定范围实际上就是n1=n3<=n2, 抓住这个寻找规律,就不会出错了。
3.除了用这种找规律的方式计算n1,n2,n3的值,还可以用枚举的方法寻找这三个数,我们知道当n2比较小的时候是不符合题目的,因此可以从小到大枚举,而相应的n1,n3则从大到小变化,直到n2>=n3=n1这个临界值,即为这三个数!注意这种方式要考虑(N+2-n2)/2无法整除的情况!

int n1, n2, n3;
for(n2=0; n2<=N; n2++) {
		if((N+2-n2)%2==0) {
			n1=n3=(N+2-n2)/2;
		}
}
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
using namespace std;
 
int main() {
	char str[90];
	scanf("%s", str);
	int length=strlen(str);	//length为字符串长度 
	int n1, n2, n3;
	n1=n3=floor((length+2)/3.0);
	n2=length+2-n1-n3;
	int i, j=length-1;
	for(i=0; i<n1-1; i++) {			//打印第一列与最后一列的字符 
		printf("%c", str[i]);
		for(int k=0; k<n2-2; k++) {		//打印中间的空格 
			printf(" ");			
		}
		printf("%c", str[j--]);
		printf("\n"); 
	} 
	for(; i<=j; i++) {
		printf("%c", str[i]);
	}
	return 0;
}

A1019 General Palindromic Number

#include <cstdio>

int main() {
	int n, b;
	scanf("%d %d", &n, &b);
	int z[200], num=0;
	do{
		z[num++]=n%b;
		n=n/b;
	}while(n!=0);
	int i;
	for(i=0; i<=num/2; i++) {
		if(z[i]!=z[num-i-1]) {
			break;
		}
	}
	if(i<=num/2) {
		printf("No\n");
	} else {
		printf("Yes\n");
	}
	for(int j=num-1; j>=0; j--) {
		printf("%d", z[j]);
		if(j>0) printf(" ");
	}
	
	return 0;
}

A1027 Colors in Mars

#include <cstdio>
char digits[13]={'0', '1','2','3','4','5','6','7','8','9','A','B','C'};
void digit_change(int n, int z[], int i) {		//i表示在数组中的存储位置 
	int num=i;
	do{
		z[num++]=n%13;
		n=n/13;
	}while(n!=0);
}

int main() {
	int n1, n2, n3;
	scanf("%d %d %d", &n1, &n2, &n3);
	int z[10];
	digit_change(n1, z, 0);
	digit_change(n2, z, 2);
	digit_change(n3, z, 4);
	for(int i=0; i<6; i+=2) {
		int temp=z[i];
		z[i]=z[i+1];
		z[i+1]=temp;
	} 
	printf("#");
	for(int i=0; i<6;i++) {
		printf("%c", digits[z[i]]);
	}
	
	return 0;
}

书中的简略写法:

#include <cstdio>
char digits[13]={'0', '1','2','3','4','5','6','7','8','9','A','B','C'};
int main() {
	int n1, n2, n3;
	scanf("%d %d %d", &n1, &n2, &n3);
	printf("#");
	printf("%c%c", digits[n1/13], digits[n1%13]);
	printf("%c%c", digits[n2/13], digits[n2%13]);
	printf("%c%c", digits[n3/13], digits[n3%13]);
	return 0;
} 

A1058 A+B in Hogwarts

注意:如果用int类型数据的话,有一组测试点显示无法通过,溢出了,因此使用long long!

#include <cstdio>

int main() {
	long long a_g, a_s, a_k, a_knuts;
	long long b_g, b_s, b_k, b_knuts;
	long long c_g, c_s, c_k, c_knuts;
	scanf("%lld.%lld.%lld %lld.%lld.%lld", &a_g, &a_s, &a_k, &b_g, &b_s, &b_k);
	a_knuts=(a_g*17+a_s)*29+a_k;
	b_knuts=(b_g*17+b_s)*29+b_k;
	c_knuts=a_knuts+b_knuts;
	c_k=c_knuts%29;
	c_g=c_knuts/29/17;
	c_s=c_knuts/29-c_g*17;
	printf("%lld.%lld.%lld", c_g, c_s, c_k);


	return 0;
}

A1001 A+B Format

已通过OJ—但是代码太繁琐了,逻辑非常混乱。各种边界情况一开始没有想到,或者想到了却忘记写进去,晕,另外负数转化为正数这个方法也给忘了。
注意:
1.int转str:除了用循环除10之外,还可以直接用sprintf(str,"%d", n)这个函数。<-----
2.str转int:可用sscanf(str, “%d”, &n);---->
另外题目规定了a,b都在106 以内,因此也可以考虑用枚举的方式!这样最快。如下:

#include <cstdio>

int main() {
	int a, b, sum;
	scanf("%d%d", &a, &b);
	sum=a+b;
	if(sum<0) {
		printf("-");
		sum *= -1;
	}
	if(sum>=1000000) {
		printf("%d,%03d,%03d", sum/1000000, sum%1000000/1000, sum%1000);
	}else if(sum>=1000){
		printf("%d,%03d", sum/1000, sum%1000);
	} else {
		printf("%d", sum);
	}
	return 0;
} 
 
#include <cstdio>
#include <cstring>

int main() {
	int a, b, c;
	scanf("%d %d", &a, &b);
	c=a+b;
	char str[15];
	sprintf(str, "%d", c);
	int len=strlen(str), num_comma, pre_comma;
	if(c==0) {
		printf("0");
		return 0;
	}
	if(str[0]=='-') {
		num_comma=(len-2)/3;	//负数的时候的逗号数量
		if(num_comma==0) {
			printf("%s", str);
			return 0;
		}
		printf("-");
		pre_comma=len-1-num_comma*3;	//第一个逗号前的数字个数 
		int i=1;
		while(str[i]!='\0') {
			for(; i<=pre_comma; i++) {
				printf("%c", str[i]);
			}
			if(i==pre_comma+1) {
				printf(",");
			}
			for(int j=0; j<3; j++) {
				printf("%c", str[i]);i++;
			}
			if(str[i]!='\0') printf(",");
			
		} 
	} else {
		num_comma=(len-1)/3;
		if(num_comma==0) {
			printf("%s", str);
			return 0;
		}
		pre_comma=len-num_comma*3;
		int i=0;
		while(str[i]!='\0') {
			for(;i<pre_comma; i++) {
				printf("%c", str[i]);
			}
			if(i==pre_comma) printf(",");
			for(int j=0; j<3; j++) {
				printf("%c", str[i]);i++;
			}
			if(str[i]!='\0') printf(",");
		}
	}
	
	return 0;
}

书中代码是在考虑了a,b的范围后给出的代码:

#include <cstdio>
int num[10];
int main() {
	int a, b, sum;
	scanf("%d %d", &a, &b);
	sum=a+b;
	if(sum<0) {
		printf("-");
		sum *= -1;
	}
	int len=0;
	do{
		num[len++]=sum%10;
		sum /= 10;
	}while(sum!=0);
	for(int k=len-1; k>=0; k--) {
		printf("%d", num[k]);
		if(k>0 && k%3==0) printf(",");
	}
	
	return 0;
} 

A1005 Spell It Right

#include <cstdio>
#include <cstring>
char num_English[10][10]={"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};

int main() {
	char number[110];
	scanf("%s", number);
	int sum=0, len=strlen(number);
	for(int i=0; i<len; i++) {
		sum += number[i]-'0';
	}
	int num=0, digits[15];		//用来保存sum的每一位
	do{
		digits[num++] = sum%10;
		sum /= 10;
	} while(sum!=0);
	for(int i=num-1; i>=0; i--) {		//从高位到低位读取 
		printf("%s", num_English[digits[i]]);
		if(i>0) printf(" "); 
	}
	
	return 0;
}

或者采用如下递归的方式:
只要得到了sum的值,然后再主程序调用dfs(sum)即可得到答案!

void dfs(int n) {
	if(n/10==0) {
		printf("%s", num_English[n%10]);
		return;
	}
	dfs(n/10);
	printf(" %s", num_English[n%10]);
}

A1035 Password

已通过OJ

#include <cstdio>
#include <cstring>

void substitute(char a[]) {
	int len=strlen(a), flag=0;		//1表示被修改过, 
	for(int i=0; i<len; i++) {
		if(a[i]=='1') {
			a[i]='@'; flag=1;
		} else if(a[i]=='0') {
			a[i]='%';flag=1;
		} else if(a[i]=='l') {
			a[i]='L';flag=1;
		} else if(a[i]=='O') {
			a[i]='o';flag=1;
		}
		if(flag==1) {
			a[11]='1';				//1表示被修改过 
		}
		flag=0;
	}
}

int main() {
	int N;		//表示输入的信息对数
	scanf("%d", &N);
	char str_password[N][12], str_name[N][12];
	for(int i=0; i<N; i++) {
		scanf("%s %s", str_name[i], str_password[i]);
		substitute(str_password[i]);
	} 
	int sum=0;			//表示被修改过的数目
	for(int i=0; i<N; i++) {
		if(str_password[i][11]=='1') sum++;
	} 
	if(sum==0 && N==1) {
		printf("There is 1 account and no account is modified");
	} else if(sum==0 && N>1) {
		printf("There are %d accounts and no account is modified", N);
	} else {
		printf("%d\n", sum);
		while(sum>0) {
			for(int i=0; i<N; i++) {
				if(str_password[i][11]=='1') {
					printf("%s %s\n", str_name[i], str_password[i]);
					sum--;
				}
			}
		}
	}
	
	
	return 0;
}

A 1077 Kuchiguse

问题:有一个测试点没有通过,暂时不知道原因是什么
以下为代码:

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

int main() {
	int N;			//表示输入的字符串行数
	scanf("%d", &N);
	getchar(); 		//吸收掉N后面的换行符号 
	char str[N][260];
	for(int i=0; i<N; i++) {
		cin.getline(str[i], 266);
	} 
	int len_str[N];			//表示存储字符串长度的数组 
	for(int i=0; i<N; i++) {
		len_str[i]=strlen(str[i]);
	}
	int kuchi=-1;				//表示第一个字符串与第二个字符串倒着看相同部分的位序 
	for(int i=len_str[0]-1, j=len_str[1]-1; i>=0 && j>=0; i--, j--) {
		if(str[0][i]==str[1][j]) {
			kuchi=i;		//表示找到了kuchi的第一个字符在零号数组中的位置 
		} else {
			break;
		}
	}
	if(kuchi==-1) {
		printf("nai");
		exit(0);
	} else {
		int len_kuchi=len_str[0]-kuchi;		//表示kuchi的长度
		int k_0=kuchi;						//表示0号数组的kuchi在其中的位序 
		for(int i=2; i<N; i++) {
			for(int j=len_str[i]-len_kuchi; j<len_str[i]; j++) {
				if(str[0][k_0]!=str[i][j]) {
					printf("nai");
					exit(0);				//如果不等,直接结束程序 
				}
				k_0++;
			}
			k_0=kuchi;
		} 
	}
	for(int i=kuchi; i<len_str[0]; i++) {
		printf("%c", str[0][i]);
	} 
	
	return 0;
}

本来书中代码有一个测试点是无法通过的, 发现把书中代码的字符串长度增加到260后编译就通过了,----迷。
以下为书中代码:

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int n, minlen=260, ans=0;
char s[100][260];

int main() {
	scanf("%d", &n);
	getchar();			//无论是用gets()还是cin.getline()都需要这一句
	for(int i=0; i<n; i++) {
		cin.getline(s[i], 260);
		int len=strlen(s[i]);
		if(len<minlen) minlen=len;
		for(int j=0; j<len/2; j++) {		//表示将所有字符串反转,便于比较 
			char temp=s[i][j];
			s[i][j]=s[i][len-j-1];
			s[i][len-j-1]=temp;
		}
	} 
	for(int i=0; i<minlen; i++) {
		char c=s[0][i];
		bool same=true;
		for(int j=1; j<n; j++) {
			if(c!=s[j][i]) {
				same=false;
				break;
			}
		}
		if(same) ans++;
		else break;
	}
	if(ans) {
		for(int i=ans-1; i>=0; i--) {
			printf("%c", s[0][i]);
		}
	} else {
		printf("nai");
	}
	return 0;
	
} 

A1082 Read Number in Chinese

问题:1.这题太繁琐了,太多个例,规律很难找啊,写了好久还是发现一堆问题没解决。?感觉自己好笨
2.如果尝试用枚举的方法解这道题也是不太可行的,例子不同,打印的东西也有很大差异。
3.主要思路是把数按节(每节四位,个十百千)分成几个小节,每个节的输出思路其实是一样的,即对于零的处理逻辑是相通的,在该节中,某个非零位前(不包括千位)如果有零的话,那么就需要在该非零位的发音前多一个零。节后的末尾根据具体情况输出亿万,为了便于代码编写,将亿万的输出写在节内数字打印的循环外面,根据是否有零及不是个位就输出亿万。。。。。
以下为书中代码:

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

char num[10][5]={"ling", "yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu"};
char wei[5][5]={"Shi", "Bai","Qian", "Wan", "Yi"};

int main() {
	char str[15];
	cin.getline(str, 15); 
	int len=strlen(str);
	int left=0, right=len-1;
	if(str[0]=='-') {
		printf("Fu");
		left++;
	}
	while(left+4<=right){
		right-=4;
	}
	while(left<len) {
		bool flag=false;
		bool isPrint=false;
		while(left<=right) {
			if(left>0 && str[left]=='0') {
				flag=true;
			} else {
				if(flag==true) {
					printf(" ling");
					flag=false;
				}
				if(left>0) printf(" ");
				printf("%s", num[str[left]-'0']);
				isPrint=true;
				if(left!=right) {
					printf(" %s", wei[right-left-1]);
				}
			}
			left++;
		}
		if(isPrint==true && right!=len-1) {
			printf(" %s", wei[(len-1-right)/4+2]);
		}
		right+=4;
	}
	return 0;
	

}

A1025 PAT Ranking

最后一个测试点无法通过,显示段错误.
问题:1.注意题目要求,最大容量应为100*300, 因此最好比30000大,这样就不会出现段错误
2.当把下面的代码的info[]改好了大小后,仍然无法通过最后一个测试点,显示答案错误,估计是因为将registration number 以long long 的形式输入输出的时候出了问题,当改成以字符串的形式输入输出的时候,通过OJ了,这也有点迷,因为题目明确说了这个数字是13位的啊,理论上说long long 应该完全没有问题啊。GU
以下为代码:

#include <cstdio>
#include <algorithm>
using namespace std;

struct  Student{
	long long regi_num;
	int score;
	int location;
	int local_rank;
	int final_rank;
}info[30010];

bool cmp(Student a, Student b) {	//比较函数 
	if(a.score!=b.score) return a.score>b.score;
	else return a.regi_num<b.regi_num;
}

int main() {
	int loca;
	scanf("%d", &loca);
	int count=0; 					//表示读入的所有行数 
	for(int i=1; i<=loca; i++) {	//i表示测试发生的地点
		int K;						//表示读入的行数
		scanf("%d", &K);
		count += K;
		for(int j=count-K; j<count; j++) {
			scanf("%lld %d", &info[j].regi_num, &info[j].score);
			info[j].location=i;
		} 	
		sort(info+count-K, info+count, cmp);	//局部排序 
		info[count-K].local_rank=1;
		for(int m=count-K+1; m<count; m++) {
			if(info[m].score==info[m-1].score) {
				info[m].local_rank=info[m-1].local_rank;
			} else {
				info[m].local_rank=m+1+K-count;
			}
		} 
	}
	sort(info, info+count, cmp);
	info[0].final_rank=1;
	for(int i=1; i<count; i++) {	//表示输入排名 
		if(info[i].score==info[i-1].score) {
			info[i].final_rank=info[i-1].final_rank;
		} else {
			info[i].final_rank=i+1;
		}
	}
	printf("%d\n", count);
	for(int i=0 ;i<count; i++) {
		printf("%lld %d %d %d\n", info[i].regi_num, info[i].final_rank, info[i].location, info[i].local_rank);
	}
	
	return 0;
}

以下为正确代码,已通过OJ

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

struct  Student{
	char regi_num[15];
	int score;
	int location;
	int local_rank;
	int final_rank;
}info[1000];

bool cmp(Student a, Student b) {	//比较函数 
	if(a.score!=b.score) return a.score>b.score;
	else return strcmp(a.regi_num, b.regi_num)<0;
}

int main() {
	int loca;
	scanf("%d", &loca);
	int count=0; 					//表示读入的所有行数 
	for(int i=1; i<=loca; i++) {	//i表示测试发生的地点
		int K;						//表示读入的行数
		scanf("%d", &K);
		count += K;
		for(int j=count-K; j<count; j++) {
			scanf("%s %d", info[j].regi_num, &info[j].score);
			info[j].location=i;
		} 	
		sort(info+count-K, info+count, cmp);	//局部排序 
		info[count-K].local_rank=1;
		for(int m=count-K+1; m<count; m++) {
			if(info[m].score==info[m-1].score) {
				info[m].local_rank=info[m-1].local_rank;
			} else {
				info[m].local_rank=m+1+K-count;
			}
		} 
	}
	sort(info, info+count, cmp);
	info[0].final_rank=1;
	for(int i=1; i<count; i++) {	//表示输入排名 
		if(info[i].score==info[i-1].score) {
			info[i].final_rank=info[i-1].final_rank;
		} else {
			info[i].final_rank=i+1;
		}
	}
	printf("%d\n", count);
	for(int i=0 ;i<count; i++) {
		printf("%s %d %d %d\n", info[i].regi_num, info[i].final_rank, info[i].location, info[i].local_rank);
	}
	
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值