【PTA刷题】乙级 1046 To 1065

博主分享了在PTA平台刷乙级1046到1065题目的经历,涉及数组操作、字符串处理、复数乘法、螺旋矩阵等算法问题。遇到的难点包括数字加密、数列片段和、住房空置率等,分享了解题技巧和常见陷阱,如数组边界、格式输入输出、特殊数值处理等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

B1046.划拳 7Min
签到题

/*B1046*/
#include <iostream>

using namespace std;

int main()
{
	int N;
	cin >> N;
	int Awin = 0, Bwin = 0;
	for (int i = 0; i < N; i++)
	{
		int AGuess, A, BGuess, B;
		cin >> AGuess >> A >> BGuess >> B;
		int sum = AGuess + BGuess;
		if (A == sum && B != sum) Awin++;
		if (B == sum && A != sum) Bwin++;
	}

	cout << Bwin << " " << Awin;

	return 0;
}

B1047.编程团体赛 9min
签到题

/*B1047*/
#include <iostream>
#include <vector>
#include <string>
#include <cctype>
#include <algorithm>
#include <stdio.h>

using namespace std;

int main()
{
	int N;
	cin >> N;
	int TeamScore[1001] = {0};

	for (int i = 0; i < N; i++)
	{
		int Tid, Pid, score;
		scanf("%d-%d %d", &Tid, &Pid,&score);

		TeamScore[Tid] += score;
	}
	int maxS = 0, maxID;
	for (int i = 1; i < 1001; i++)
	{
		if (TeamScore[i] > maxS)
		{
			maxS = TeamScore[i];
			maxID = i;
		}
	}
	printf("%d %d", maxID, maxS);


	return 0;
}

B1048.数字加密 51min
自己做了非常久,主要是被不知道A长还是B长卡住了。柳神使用了补位的方法非常好,我觉得比判断size是否大于0要好理解而且不容易出错。
出现了几个用法:
1.reverse(A.begin(),B.end()); 翻转数组
2.str.append(你要补多少个,‘你要补啥字符’);用于str的末尾补全。
3.str[xxx] = {“asdansjdnsa”} 用于方便的转化int和char。非常机智
4.再次强调string的方便之处,可以直接 str += 某些字符或字符串。要学会用这个性质。

/*B1048*/
#include <iostream>
#include <vector>
#include <string>
#include <cctype>
#include <algorithm>
#include <stdio.h>

using namespace std;

int main()
{
	string A, B,c;
	cin >> A >> B;

	string tmp;
	int Asize = A.length(), Bsize = B.length();

	reverse(A.begin(), A.end());
	reverse(B.begin(), B.end());//翻转

	if (Asize > Bsize)
		B.append(Asize - Bsize, '0');
	else
		A.append(Bsize - Asize, '0');//短的那个string补0

	char str[14] = { "0123456789JQK" };
	for (int i = 0; i < B.size(); i++)
	{
		if (i % 2 == 0)
			c += str[((A[i] - '0') + (B[i] - '0')) % 13];
		else
		{
			if (B[i] - A[i] < 0)
				c += str[(B[i] - '0') - (A[i] - '0') + 10];
			else
				c += str[(B[i] - '0') - (A[i] - '0')];
		}
	}
	for (int i = c.length() - 1; i >= 0; i--)
		cout << c[i];


	return 0;
}

1049.数列的片段和 fail
没做出来。
解法:假设我们选取的片段包括某个数字n,然后该片段的头指针有i种选择,片段的尾指针有(N-1-i)种选择,这样这个指针组合就是 i * (N-1-i)种。但实际上不知道为啥后面变成了 n xi x(N-i+1)。

/*B1049*/
#include <iostream>
#include <vector>
#include <string>
#include <cctype>
#include <algorithm>
#include <stdio.h>

using namespace std;

int main()
{
	int N;
	cin >> N;
	
	double sum = 0.0, n;
	for (int i = 0; i < N; i++)
	{
		cin >> n;
		sum += n*i*(N - i + 1);
	}
	printf("%.2lf",sum);
	
	return 0;
}

B1050.螺旋矩阵 fail
第一次做: 打印没想出办法,只计算出了mn。
第二次做:高度参考了柳神的方法。 每个口字型做一个level,用i(当前level层数)以及j(每一笔必定只有一个变量,要么是行,要么是列,J就表示这个变化的东西),来表示出矩阵的每一个位置。

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string>
#include <map>
#include <vector>
#include <math.h>

using namespace std;

bool cmp(int a ,int b)
{
	return a > b ? true : false;
}

int main()
{
	int N,m,n;
	cin >> N;
	
	for (n = sqrt(N); n > 0; n--)
	{
		if (N % n == 0)
			break;
	}
	m = N / n;
	vector<int> ori(N);
	for (int i = 0; i < N; i++)
	{
		cin>>ori[i];
	}
	sort(ori.begin(), ori.end(), cmp);
	vector<vector<int> > b(m, vector<int>(n));//创建矩阵

	int level = m / 2 + m % 2;
	int t = 0;

	//填入原理:i是当前层数,j是变化的一笔,这一笔可以是行也可以是列。
	//i,j,m,n来表示矩阵的每一个位置。只要细心是不会出错的。
	for (int i = 0; i < level; i++)//外层循环控制层数
	{
		for (int j = i; j <= n - 1 - i && t <= N - 1; j++)
			b[i][j] = ori[t++];
		for (int j = i + 1; j <= m - 2 - i && t <= N - 1; j++)
			b[j][n -1-i] = ori[t++];
		for (int j = n - 1 - i; j >= i && t <= N - 1; j--)
			b[m - 1 - i][j] = ori[t++];
		for (int j = m - 2 - i; j >= i + 1 && t <= N; j--)
			b[j][i] = ori[t++];
	}
	for (int i = 0; i < m; i++)
	{
		for (int j = 0; j < n; j++)
		{	
			if(j != n-1)
				cout << b[i][j]<<" ";
			else
				cout << b[i][j] << "\n";
		}
	}

	return 0;
}

B1051.复数乘法 12min
有两个点没过,看题解是说A和B如果大于-0.005但小于0时,会出错。本来应该输出0.00,但输出了-0.00.等于说要排除这个特殊情况。但自己做的时候没发现。(我也不知道咋发现)
记得cos,sin在math.h里面。

/*B1051*/
#include <iostream>
#include <vector>
#include <string>
#include <cctype>
#include <algorithm>
#include <stdio.h>
#include <math.h>

using namespace std;


int main()
{
	double r1, r2, p1, p2;
	cin >> r1 >> p1 >> r2 >> p2;

	double A, B;
	 
	A = r1*r2*( cos(p1)*cos(p2) - sin(p1)*sin(p2));
	B = r1*r2*( sin(p1)*cos(p2) + sin(p2)*cos(p1));

	if (A != 0) {
		if (B > 0)
			printf("%.2lf+%.2lfi", A, B);
		else if (B < 0)
			printf("%.2lf-%.2lfi", A, abs(B));
		else if (B == 0)
			printf("%.2lf", A);
	}
	else
	{
		if (B > 0)
			printf("%.2lfi", B);
		else if (B < 0)
			printf("-%.2lfi", abs(B));
		else
			printf(0);
	}
	return 0;
}

B1052.卖个萌 32min
主要考编码。用一个装有vector的数组存放颜文字组。

/*B1052*/
#include <iostream>
#include <vector>
#include <string>
#include <cctype>
#include <algorithm>
#include <stdio.h>
#include <math.h>

using namespace std;


int main()
{
	string str;
	vector<string> vec[3];

	//string str = "[a][**][kkk]";
	//vector<string> vec;
	//while (str.find('[') != string::npos)
	//{
	//	int a = str.find('['), b = str.find(']');
	//	string tmp = str.substr(a + 1, b - a - 1);
	//	str = str.substr(b + 1);
	//	vec.push_back(tmp);
	//}
	//for (int i = 0; i < 3; i++)
	//	cout << " " << vec[i];


	for (int i = 0; i < 3; i++)
	{
		getline(cin,str);
		while (str.find('[') != string::npos)
		{	
			int a = str.find('['), b = str.find(']');
			string tmp = str.substr(a+1,b-a-1);
			str = str.substr(b + 1);
			vec[i].push_back(tmp);
		}
	}

	int N;
	cin >> N;
	for (int i = 0; i < N; i++)
	{
		int a, b, c, d, e;
		cin >> a >> b >> c >> d >> e;
		if (a <= vec[0].size() && e <= vec[0].size() && b <= vec[1].size()
			&& d <= vec[1].size() && c <= vec[2].size())
		{
			cout << vec[0][a] << "(" << vec[1][b] << vec[2][c]
				<< vec[1][d] << ")" << vec[0][e];
		}
		else
			cout << "Are you kidding me? @\\/@";

		cout << "\n";
	}
	


	return 0;
}

B1053.住房空置率 24min
难点主要在审题上,题意要仔细看。
在printf中,两个百分号可以打印出一个百分号%%。

/*B1053*/
#include <iostream>
#include <vector>
#include <string>
#include <cctype>
#include <algorithm>
#include <stdio.h>
#include <math.h>

using namespace std;


int main()
{
	int N, D;
	double e;
	cin >> N >> e >> D;
	
	int Maybe = 0, Comfirm = 0;

	for (int i = 0; i < N; i++)
	{
		int d,LowerNum = 0;
		double used;
		cin >> d;
		for (int j = 0; j < d; j++)
		{
			cin >> used;
			if (used < e) LowerNum++;
		}
		if (((double)LowerNum / (double)d > 0.5) && d <= D)
			Maybe++;
		else if (((double)LowerNum / (double)d > 0.5) && d > D)
			Comfirm++;

	}
	double MaybeRate = ((double)Maybe / (double)N) * 100;
	double ConfirmRate = ((double)Comfirm / (double)N) * 100;

	printf("%.1lf%% %.1lf%%", MaybeRate,ConfirmRate);



	return 0;
}

B1054.求平均值 53min
自己一开始用常规方法慢慢一个一个条件判断,非常麻烦。柳神使用了格式输入输出的方法,然后判断按格式输入后和原本的str做对比,如果有哪怕一个对应位置的字符不一样,都是要被标记删除的,方便了很多。
1.sscanf(读取源头,“格式”,读到之后放置的地址)
2.sprintf(打印后结果放置的地方,“按某格式”,源头) 和printf一模一样几乎,只不过本来打印在屏幕上变成了打印到第一个参数的位置。
3.如果c++和c混用,printf啥的要用c_str()来吧cpp的string类转换为char[];

我的代码:

/*B1054*/
#include <iostream>
#include <vector>
#include <string>
#include <cctype>
#include <algorithm>
#include <stdio.h>
#include <math.h>

using namespace std;


int main()
{
	int N;
	double Sum = 0.00;
	int legel = 0;
	cin >> N;

	for (int i = 0; i < N; i++)
	{	
		int flag = 1; //一开始默认合法
		int PlotNum = 0;//小数点数量
		string str;
		cin >> str;
		for (int j = 0; j < str.length(); j++)
		{
			if (isalpha(str[j]))//是个字母
			{
				flag = 0;
				break;
			}
			else if ( str[j] == '.')//是小数点
				PlotNum++;

			if (PlotNum > 1)
			{
				flag = 0;
				break;
			}
		}

		int flag2 = 1;//控制小数点位数的flag
		if (flag == 0)
			printf("ERROR: %s is not a legal number\n", str.c_str());
		else //暂时合法情况(是个正常数字)
		{	
			if (str.find('.') != string::npos)//找到了一个小数点
			{
				if (str.length() - str.find('.') >= 4)//超过两位小数
					flag2 = 0;
			}

			double tmp = stod(str);
			if (tmp >= -1000 && tmp <= 1000 && flag2 == 1)
			{
				legel++;
				Sum += tmp;
			}
			else
				printf("ERROR: %s is not a legal number\n", str.c_str());

		}
	}

	if (legel == 0)
		printf( "The average of 0 numbers is Undefined\n");
	else if (legel == 1)
		printf( "The average of 1 numbers is %lf\n",Sum);
	else
		printf("The average of %d numbers is %.2lf\n", legel,Sum/(double)legel);



	return 0;
}

B1055.集体照 fail
思路基本上正确了,但是不知道要设置t这个在ori中移动的指针。而且题目有点晦涩,我们站在完全面对拍照的学生的视角,所以啥都是反的,并且最后多出来的人,也一并放于最后一排(却是第一排输出),而不是一开始理解的N%K后,多余的自成一排。
理清思路:
1.用sort排序
2.用while控制行数,只有第一行 row = k时,m是要加入多余的人数的,别的行的m就是N/K;
3.用一个临时的vector来装每一行具体的打印信息。
4.先确立中间位置m/2,然后分别去找左边最邻近的j = m/2-1,用j–来控制次临近。j代表临时的打印vec的角标,i代表对应ori中的角标。
5.每循环一次,t = t+m代表t在ori中的指针移动。row–表示下一行。

/*B1055*/
#include <iostream>
#include <vector>
#include <string>
#include <cctype>
#include <algorithm>
#include <stdio.h>
#include <math.h>

using namespace std;

struct Student 
{
	string name;
	int h;
};

bool cmp(Student stu1, Student stu2)
{
	if (stu1.h > stu2.h) return true;
	else if (stu1.h == stu2.h)
	{
		return stu1.name < stu2.name ? true : false;
	}
	else
		return false;
}

int main()
{
	int N, K;
	cin >> N >> K;
	vector<Student> ori;

	for (int i = 0; i < N; i++)
	{
		Student stu;
		cin >> stu.name >> stu.h;
		ori.push_back(stu);
	}

	sort(ori.begin(), ori.end(),cmp);
	int t = 0;//控制在ori中游走的指针(程序核心)
	int row = K;
	int m;//当前行有m个人
	while (row)
	{
		if (row == K)
			m = N - N / K * (K - 1);//多余的人数也一起放输出的第一行
		else
			m = N / K;

		vector<string> vec(m);//大小为m的动态数组
		vec[m / 2] = ori[t].name;//中间的人定了

		int j = m / 2 - 1;//左边
		for (int i = t + 1; i < t + m; i = i + 2)//不触及m,则一直填
			vec[j--] = ori[i].name;

		j = m / 2 + 1;//右边
		for (int i = t + 2; i < t + m; i = i + 2)
			vec[j++] = ori[i].name;

		cout << vec[0];
		for (int i = 1; i < vec.size(); i++)//输出当前行
			cout << " "<<vec[i];
		cout << "\n";

		t = t + m; //ori的起始指针移动
		row--;

	}

	return 0;
}

B1056.组合数的和 9min
签到题

/*B1056*/
#include <iostream>
#include <vector>
#include <stdio.h>

using namespace std;

int main()
{
	int N;
	cin >> N;
	vector<int> ori;
	for (int i = 0; i < N; i++)
	{
		int n;
		cin >> n;
		ori.push_back(n);
	}

	int i, j,tmp1,tmp2,Sum = 0;
	for (i = 0; i < N; i++)
	{
		for (j = i + 1; j < N; j++)
		{
			tmp1 = ori[i] * 10 + ori[j];
			tmp2 = ori[j] * 10 + ori[i];
			Sum = Sum + tmp1 + tmp2;
		}
	}

	cout << Sum;

	return 0;
}

B1057.数零一 13min
比较简单。
稍微注意一下要用str的拼接的话,需要用to_string来转化int为string。进制转换无非就是不停的除进制数,然后每次除出来的余数就是本轮需要保留的数字。

/*B1057*/
#include <iostream>
#include <vector>
#include <string>
#include <cctype>
#include <algorithm>
#include <stdio.h>
#include <math.h>

using namespace std;


int main()
{
	string str;
	getline(cin, str);

	int Sum = 0;
	for (int i = 0; i < str.length(); i++)
	{
		if (isalpha(str[i]))
		{
			if (isupper(str[i]))
				Sum += (str[i] - 'A' + 1);
			else if (islower(str[i]))
				Sum += (str[i] - 'a' + 1);
		}
			
	}
	string result;
	while (Sum != 0)
	{
		int Yu = Sum % 2;
		result += to_string(Yu);
		Sum /= 2;
	}
	int Zero = 0, One = 0;
	for (int i = 0; i < result.length(); i++)
	{
		if (result[i] == '0') Zero++;
		if (result[i] == '1') One++;
	}

	cout << Zero << " " << One;


	return 0;
}

B1058.选择题 fail 62min
读取太复杂了,估计是空格啥的没读好,结果错了。有空再debug。
不过可以学到两点:
1.可以用scanf一点点按格式读取信息
2.如果vs不能用scanf,则在第一行(所有的Include之前)加上 #define _CRT_SECURE_NO_DEPRECATE

第三次做,终于AC了,用时半小时左右。注意,中间那个选项数不对不能跳过,因为这样会干扰scanf的读取(不用这个值也要把该读的多余的部分读取掉)。

/*B1055*/
#define _CRT_SECURE_NO_DEPRECATE
#include <iostream>
#include <vector>
#include <string>
#include <cctype>
#include <algorithm>
#include <stdio.h>
#include <math.h>


using namespace std;

struct Problem
{
	int score;
	int opp;
	int correct;
	string ans;
};


int main()
{
	int M, N;
	cin >> N >> M;

	vector<Problem> pro;
	for (int i = 0; i < M; i++)
	{
		Problem ques;
		string tmp;
		cin >> ques.score >> ques.opp >> ques.correct;
		for (int j = 0; j < ques.correct; j++)
		{
			cin >> tmp;
			ques.ans += tmp;
		}

		pro.push_back(ques);
	}

	vector<int> Wrong(M); //错题表
	for (int i = 0; i < M; i++)//初始化
		Wrong[i] = 0;

	for (int i = 0; i < N; i++)//人数
	{	
		int StuScore = 0;

		for (int j = 0; j < M; j++)//题号
		{	
			int cor,flag = 1;
			scanf("(%d", &cor);
			if (cor != pro[j].correct)//若正确数不对,直接判错
				flag = 0;

			string cstr;
			for (int k = 0; k < cor; k++)
			{	
				char c;
				scanf(" %c",&c);
				cstr += to_string(c);
			}
			if (j != M - 1)
				scanf(") ");
			else
				scanf(")");

			if (cstr != pro[j].ans)//选项不对,判错
				flag = 0;

			if (flag == 0) Wrong[j]++;
			else if (flag == 1) StuScore += pro[i].score;
		}

		printf("%d", StuScore);
		if (i != N - 1)
			printf("\n");
	}

	int MostT = 0, ID;
	for (int i = 0; i < M; i++)
	{
		if (Wrong[i] > MostT)
			MostT = Wrong[i];
	}

	if (MostT == 0)
		printf("Too simple");
	else
	{
		printf(" %d", MostT);
		for (int i = 0; i < M; i++)
		{
			if (Wrong[i] == MostT)
				printf(" %d", i + 1);
		}
	}
	return 0;
}

第三次做,AC版本:

#include <iostream>
#include <string>
#include <vector>
#include <stdio.h>
#include <map>
#include <algorithm>

using namespace std;
//emuB159202003070095

int problem[105] = {0};
int stu[1005] = { 0 };

struct infomation
{
	int full, nums, cor;
	vector<char> v;
};

int main()
{	
	int M, N;
	cin >> N >> M;
	map<int,infomation> m;
	for (int i = 1; i <= M; i++)//处理题
	{
		infomation info;
		cin >> info.full >> info.nums >> info.cor;
		for (int j = 0; j < info.cor; j++)
		{	
			char tmp;
			cin >> tmp;
			info.v.push_back(tmp);
		}
		m[i] = info;
	}

	for (int people = 0; people < N; people++)//处理人
	{
		for (int i = 1; i <= M; i++)//每个人做的每个题单独分析
		{	
			int flag = 1;//默认做对了
			int ntmp;
			scanf("\n(%d", &ntmp);
			if (ntmp != m[i].cor)//选项数不对立刻错
				flag = 0;
			for (int j = 0; j < ntmp ; j++)//逐选项分析
			{
				char ans;
				scanf(" %c", &ans);
				if (find(m[i].v.begin(), m[i].v.end(), ans) == m[i].v.end())
				{
					flag = 0;
					//break;
				}
			}
			scanf(")");
			if (i != M) scanf(" ");
		
			if (flag == 0)
				problem[i]++;
			else
				stu[people] += m[i].full; //做对了加分
		}
	}

	for (int i = 0; i < N; i++)//个人分数
		cout << stu[i] << "\n";

	int maxtimes = -999;
	for (int i = 1; i < 105; i++)
	{
		if (problem[i] > maxtimes)
			maxtimes = problem[i];
	}
	if (maxtimes == 0)
	{
		cout << "Too simple";
		return 0;
	}
	cout <<maxtimes;
	for (int i = 1; i < 105; i++)
	{
		if (problem[i] == maxtimes)
			cout <<" "<<i;
	}

	return 0;
}

B1059.C语言竞赛 43min
格式错误搞了半天,最后才发现冒号后面有个空格。自己用双for循环,用角标表示排序,数组中储存string形式的ID,挂了俩点。
还有记得IsPrime的i要从2开始,因为素数是排除1和自己本身的除数。
柳神用一个大数组装所有可能的四位数ID的排名,这样就可以点对点查找。再用一个set来装已查过的ID,这样复杂度低多了。根据这俩数组组合就能搞出所有情况。(也可以不用set来做,直接用ori中的负数表示已经检查过就可以了)。

/*B1059*/
#include <iostream>
#include <vector>
#include <stdio.h>
using namespace std;

bool IsPrime( int a)
{
	for (int i = 2; i * i <= a; i++)
		if (a % i == 0) 
			return false;
	return true;
}
int ori[10000] = {0};

int main()
{
	int N;
	cin >> N;

	for (int i = 0; i < N; i++)
	{
		int n;
		cin >> n;
		ori[n] = i+1;
	}
	int K;
	cin >> K;

	for (int i = 0; i < K; i++)
	{
		int x;
		cin >> x;
		if (ori[x] == 0)
			printf("%04d: Are you kidding?\n",x);
		else
		{
			if (ori[x] == 1) 
			{
				printf("%04d: Mystery Award\n", x);
				ori[x] = -1;
			}
			else if (IsPrime(ori[x]) && ori[x] != -1) 
			{
				printf("%04d: Minion\n", x);
				ori[x] = -1;
			}
			else if (ori[x] == -1)
				printf("%04d: Checked\n", x);	
			else {
				printf("%04d: Chocolate\n", x);
				ori[x] = -1;
			}
		}

	}

	return 0;
}


但set 的用法要掌握。
set可以自动按从小到大的顺序排序。用find的位置不等于尾指针的位置来确定是否有找到。

set<int> ss;
if(ss.find(我要找的元素) == ss.end())
		ss.insert(我要插入的元素);

ss.erase(我要删除的元素)

B1060.爱丁顿数 14min
有了前一题的经验,这题变成了签到题。不过有个点卡了一个段错误(数组越界),原因是miles大小开小了(虽然说非常反常规,人不可能一天骑行999999英里)。
再次提醒了我做题时数组的角标做什么变量的重要性。

/*B1060*/
#include <iostream>
#include <vector>
#include <string>
#include <cctype>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#include <set>
using namespace std;

int miles[1000000] = {0};

int main()
{
	int N;
	cin >> N;
	for (int i = 0; i < N; i++)
	{
		int n;
		cin >> n;
		miles[n]++;
	}

	int SumDay = 0,i;
	for (i = 1000000 -1; i >= 0; i--)
	{
		if (SumDay >= i)
			break;
		else
			SumDay += miles[i];
	}

	cout << i;
	return 0;
}

B1061.判断题 7min
签到题

/*B1061*/
#include <iostream>
#include <vector>
#include <string>
#include <cctype>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#include <set>
using namespace std;

int pro[101] = { 0 };
int ans[101] = { -1 };
int stu[101] = { 0 };

int main()
{
	int N,M;
	cin >> N >> M;
	for (int i = 0; i < M; i++)
		cin >> pro[i];
	
	for (int i = 0; i < M; i++)
		cin >> ans[i];

	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < M; j++)
		{
			int myans;
			cin >> myans;
			if (myans == ans[j])
				stu[i] = stu[i] + pro[j];
		}
	}

	for (int i = 0; i < N; i++)
		cout << stu[i] << "\n";
	


	return 0;
}

B1062.最简分数 fail / 36min (核心,辗转相除法求最大公约数)
辗转相除法:本轮用a被除数除以除数b,得到余数a%b。若a%b != 0,则另被除数等于除数,除数等于余数,继续计算。
在程序中,以b == 0为终止条件,若满足条件,则说明上一轮的除数(即本轮的被除数a)已经是最大公约数了。
所以递归为

gcd(int a , int b )
{
	return b == 0? a: gcd(b,a%b);
}

此外,set的迭代器用法莫名其妙中断了,目前原因未知,只能多开一个数组用角标来控制循环。

/*B1062*/
#include <iostream>
#include <vector>
#include <string>
#include <cctype>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#include <set>

using namespace std;

int gcd(int a, int b)
{
	return b == 0 ? a : gcd(b, a%b);  
	//b为0时说明上一轮的除数(即本轮的a)已经是最大公约数了,为结束信号
	//否则一直辗转相除,用本轮除数除以本轮余数
}

bool IsSimplest(int x, int c)
{
	if (gcd(x, c) != 1) return false;
	else return true;
}

int main()
{	
	int a1, a2, b1, b2, c;
	scanf("%d/%d ", &a1, &b1);
	scanf("%d/%d ", &a2, &b2);
	scanf("%d", &c);

	double A = (double)a1 / (double)b1;
	double B = (double)a2 / (double)b2;
	if (A > B)
		swap(A, B);

	vector<int> tmp;
	for (int i = 0; i < c; i++)
	{
		double t = (double)i / (double)c;
		if (t > A && t < B)
			tmp.push_back(i);
	}
	
	vector<int> res;
	for (int i = 0;i < tmp.size();i++)
	{
		if (IsSimplest(tmp[i], c))
			res.push_back(tmp[i]);
	}

	if (!res.empty())
	{
		cout << res[0] << "/" << c;
		for (int i = 1; i < res.size(); i++)
			cout << " " << res[i] << "/" << c;
	}
	

	return 0;
}

B1063.计算谱半径 9min
签到题
注意用printf精确小数点,已经是四舍五入输出了。

/*B1063*/
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <math.h>

using namespace std;

int main()
{	
	int N;
	cin >> N;

	double Max = 0.0;
	for (int i = 0; i < N; i++)
	{
		double a, b;
		cin >> a >> b;
		double tmp;
		tmp = sqrt(a*a + b*b);
		if (tmp > Max)
			Max = tmp;
	}

	printf("%.2lf", Max);

	return 0;
}

B1064.朋友数 11min
签到题

/*B1064*/
#include <iostream>
#include <vector>
#include <string>
#include <cctype>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#include <set>

using namespace std;

int Summary[41] = { 0 };

int main()
{	
	int N;
	cin >> N;

	for (int i = 0; i < N; i++)
	{
		string str;
		cin >> str;
		int tmp = 0;
		for (int j = 0; j < str.length(); j++)
		{	
			int a = str[j] - '0';
			tmp += a;
		}
		Summary[tmp]++;
	}
	int cnt = 0;
	vector<int> vec;
	for (int i = 0; i < 41; i++)
	{
		if (Summary[i] != 0)
		{
			vec.push_back(i);
			cnt++;
		}
	}
	if (cnt) 
	{	
		cout << cnt << "\n";
		cout << vec[0];
		for (int i = 1; i < cnt; i++)
			cout << " " << vec[i];
	}

	return 0;
}

B1065.单身狗 21min
整体难度不大,本以为要超时,但是顺利一把过了。有两三个改进的地方和补充点。
1.数组的初始化。
int a [100] = {0}是可以这样写的,因为第一个元素赋值0,然后不足的位置全以初始值(也是0)来补足。
但如果是int a [5] = {-1},结果其实是{-1,0,0,0,0}。所以还是老老实实循环初始化吧。

2.容器的find()函数,返回一个迭代器位置。所以进行判断的时候一定要写find() == vec.end()才不会报错。

3.柳神用了另一个大数组表示参加人数,cin的时候把相应角标赋值1即可,省去了find()这个耗时的过程。

4.用set自动排序,就不用再sort一下了。

/*B1065*/
#include <iostream>
#include <vector>
#include <string>
#include <cctype>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#include <set>

using namespace std;

int couple[100000];

int main()
{	
	int N;
	cin >> N;
	for (int i = 0; i < 100000; i++)//初始化
		couple[i] = -1;

	for (int i = 0; i < N; i++)
	{
		int a, b;
		cin >> a >> b;
		couple[a] = b;
		couple[b] = a;
	}
	int M;
	cin >> M;
	vector<int> join;
	vector<int> res;
	for (int i = 0; i < M; i++)
	{
		int j;
		cin >> j;
		join.push_back(j);
	}
	for (int i = 0; i < M; i++)
	{
		if (couple[join[i]] == -1)
			res.push_back(join[i]);
		else if (find(join.begin(), join.end(), couple[join[i]]) == join.end())
			res.push_back(join[i]);
	}

	sort(res.begin(), res.end());
	int size =  res.size();
	cout << size<<"\n";
	if (size != 0) 
	{	
		printf("%05d", res[0]);
		for (int i = 1; i < res.size(); i++)
			printf(" %05d", res[i]);
	}


	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值