B1026.程序运行时间
1.四舍五入的写法。利用小数部分加上0.5则除法进1的性质。在被除数的基础上加上0.5乘以除数即可。例如题中的0.5*100 =50,则只要在被除数上加50就可以实现四舍五入。
2.int 2的31次方,10的9次方数量级
longlong 2的63次方,大概是10的19次方
/*B1026*/
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <math.h>
#include <stack>
using namespace std;
//int 2的31次方,10的9次方数量级
//longlong 2的63次方,大概是10的19次方
int main()
{
int c1, c2;
cin >> c1 >> c2;
int result = (c2 - c1+50)/100;//四舍五入,如果小数部分大于0.5则进位了,50由0.5*100得出
int hour = result / 3600;
result = result % 3600;
int minute = result / 60;
int second = result % 60;
printf("%02d:%02d:%02d", hour, minute, second);
return 0;
}
B1027.打印沙漏
1.中央对齐这个功能是可以根据每行数据的规律实现的。调试打印变量多要注意。
2.程序核心是找出合适的外场数量即可。
/*B1027*/
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <math.h>
#include <stack>
using namespace std;
int Shulie[100];
int main()
{
Shulie[0] = 1;
for(int i = 1,j = 3;Shulie[i-1]<1005;i++,j+=2)//初始化数列数组
Shulie[i] = Shulie[i - 1] + 2 * j;
int N;
char OutPut;
cin >> N>>OutPut;
int i = 0;
for (; i < 100; i++)
{
if (N < Shulie[i]) break;
}
int FinalNum = Shulie[i - 1];//找出真实的总数
int ExtraNum = N - FinalNum;
int TmpSum = 0;
int j = 1;
for (;TmpSum < (FinalNum + 1) / 2; j += 2)
{
TmpSum += j;
}
j = j - 2;
int WaiChen = j;//找出了最外层个数
while (j>0)//递减打印
{
int x = j;
for (int z = (WaiChen - x) / 2; z > 0; z--)
cout << " ";
for (; x > 0; x--) {
cout << OutPut;
}
cout << "\n";
j -= 2;
}
j = 1;
while (j<WaiChen)//递减打印
{
j += 2;
int x = j;
for (int z = (WaiChen - x) / 2; z > 0; z--)
cout << " ";
for (; x > 0; x--) {
cout << OutPut;
}
cout << "\n";
}
cout << ExtraNum;
return 0;
}
B1028.人口普查
1.要习惯***字符串是可以直接比较大小的***,比转换成Int来要方便的多。
2.自己写的时候过于依赖容器和sort。要注意如果***只是为了找最小最大值,完全可以用赋值来做***,更方便。
3.柳神的代码相比自己的优势太大。
/*B1028*/
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <math.h>
#include <stack>
using namespace std;
int main()
{
int n, cnt = 0;
cin >> n;
string name, birth, maxname, minname;
string maxbirth ="1814/09/06" , minbirth = "2014/09/06";//反着定初始值
for (int i = 0; i < n; i++)
{
cin >> name >> birth;
if (birth >= "1814/09/06" && birth <= "2014/09/06")
{
cnt++;
if (birth >= maxbirth)
{
maxbirth = birth;
maxname = name;
}
if (birth <= minbirth)
{
minbirth = birth;
minname = name;
}
}
}
if(cnt!= 0)
cout << cnt << " " << minname << " " << maxname;
return 0;
}
B1029.旧键盘(参考柳神用法)
1.string.find()函数的用法,返回一个int索引值。当str.find(某char) == string::nops代表没找到。
2.toupper()小写转大写,原本是大写不变。 tolower()是反过来的。
3.字符串的增加直接用加号就可以了 str+=char;
/*B1029*/
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <math.h>
#include <stack>
using namespace std;
int main()
{
string s1, s2,ans;
cin >> s1>> s2;
for (int i = 0; i < s1.length(); i++)
{
if (s2.find(s1[i]) == string::npos && ans.find(toupper(s1[i])) == string::npos)
ans += toupper(s1[i]);
}
for (int i = 0; i < ans.length(); i++)
cout << ans[i];
return 0;
}
B1030.完美数列 13min
自己做的思路和柳神完全一样,出了一个超时点。
/*B1030*/
#include <iostream>
#include <stdio.h>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int N, p;
cin >> N >> p;
vector<int> vec;
for (int i = 0; i < N; i++)
{
int x;
cin >> x;
vec.push_back(x);
}
sort(vec.begin(), vec.end());
int MaxCnt = 0,cnt = 0;
for (int i = 0; i < N; i++)
{
int mp = vec[i] * p;
for (int j = i; j < N; j++)
{
if (vec[j] <= mp)
{
cnt = j - i + 1;
}
else
break;
}
if (cnt > MaxCnt)
MaxCnt = cnt;
}
cout << MaxCnt;
return 0;
}
B1031.检查身份证 21min
1.注意char的数字不等于int的同数字,编码不同,所以效验数组M里面所有的字符都要打单引号。
2.检查是否是数字直接 char>=‘0’ && char<= ‘9’ 即可,和检验大小写字母异曲同工。
/*B1030*/
#include <iostream>
#include <stdio.h>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int Right[17] = {7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
char M[11] = {'1','0','X','9','8','7','6','5','4','3','2'};
int N;
cin >> N;
vector<string> Result;
for (int i = 0; i < N; i++)//读入N个ID
{
string ID;
cin >> ID;
int HaveZiMu = 0;//加入flag
int sum = 0, Z; //初始化sum,和Z
for (int j = 0; j < 17; j++)//每个ID的前17个字符
{
if (ID[j] >= '0' && ID[j] <= '9')//该字符是数字
{
int num;
num = ID[j] - '0';
sum += num *Right[j];
}
else//不是数字直接输出
{
HaveZiMu = 1;
Result.push_back(ID);//输出
break;
}
}
if (HaveZiMu == 0) //不含字母的情况下
{
Z = sum % 11;
if (M[Z] != ID[17])//最后一位不等,推入结果容器
Result.push_back(ID);
}
}
if (Result.size() == 0)
cout << "All passed";
else
{
for (int i = 0; i < Result.size(); i++)
{
cout << Result[i] << "\n";
}
}
return 0;
}
B1032.挖掘机技术哪家强 6min
签到题
/*B1032*/
#include <iostream>
#include <stdio.h>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int N;
cin >> N;
int School[100000] = { 0 };
for (int i = 0; i < N; i++)
{
int school,score;
cin >> school >> score;
School[school] += score;
}
int ID, Max = 0;
for (int i = 0; i < 100000; i++)
{
if (School[i] > Max)
{
ID = i;
Max = School[i];
}
}
cout << ID << " " << Max;
return 0;
}
B1034.有理数四则运算 fail * 2
究其原因,不会求最大公约数。已经碰到三次都不会,必须记住嗷,小学的辗转除余(注意除的是余数!下一轮是被除数除余数!直到被除数都是0为止!)
说到底就一行代码的递归!:
int gcd(int a, int b)//辗转相除
{
return b == 0 ? a : gcd(b, a % b);
}
吸收思想! 涉及正负号的看看能不能全部绝对值运算,在异号的时候用输出“-”来做。
#include <iostream>
#include <string>
#include <vector>
#include <stdio.h>
#include <map>
#include <algorithm>
using namespace std;
//emuB159202003070095
int gcd(int a, int b)//辗转相除
{
return b == 0 ? a : gcd(b, a % b);
}
string Zuijian( int a, int b)
{
int k = 0,flag = 1;//一开始默认为正数
if ((a < 0 && b> 0) || (a > 0 && b < 0) ) flag = 0;//是负数
a = abs(a), b = abs(b);
if (a > b)
{
k = a / b;
a = a % b;
}
string str;
if (a == 0 && k == 0)
{
str = "0";
return str;
}
if (b == 0) return "Inf";//排除两种特殊情况
int t = gcd(a, b);//求出最大公约数
t = abs(t);
if (flag == 0) str += "(-";
if (k == 0)
str += to_string(a/t) + "/" + to_string(b/t);
else
{
if (a != 0)
str += to_string(k) +' '+ to_string(a/t) + '/' + to_string(b/t);
else
str += to_string(k);
}
if (flag == 0) str += ")";
return str;
}
int main()
{
int a, b, c, d;
scanf("%d/%d %d/%d", &a, &b, &c, &d);
string Aout, Bout;
Aout = Zuijian(a,b);
Bout = Zuijian(c, d);
int sumZ = a * d + c * b;
int sumM = b * d;
string sumS = Zuijian(sumZ, sumM);
cout << Aout << " + " << Bout << " = " << sumS<<"\n";
int decZ = a * d - c * b;
string decS = Zuijian(decZ, sumM);
cout << Aout << " - " << Bout << " = " << decS<<"\n";
int chengZ = a * c;
string chengS = Zuijian(chengZ, sumM);
cout << Aout << " * " << Bout << " = " << chengS<<"\n";
int chuZ = a * d, chuM = b * c;
string chuS;
if (chuM == 0)
chuS = "Inf";
else
chuS = Zuijian(chuZ, chuM);
cout << Aout << " / " << Bout << " = " << chuS;
return 0;
}
B1036.和奥巴马一起编程 7min
签到题
/*B1036*/
#include <iostream>
#include <stdio.h>
#include <string>
#include <vector>
#include <algorithm>
#include <cctype>
using namespace std;
int main()
{
int N;
char C;
cin >> N >> C;
int ColNum = (N + 1) / 2 - 2;//列数四舍五入,去头去尾
for (int i = 0; i < N; i++)
cout << C;
for (int i = 0; i < ColNum; i++)
{
cout << "\n";
for (int j = 0; j < N; j++)
{
if (j == 0 || j == N -1) cout << C;
else cout << " ";
}
}
cout << "\n";
for (int i = 0; i < N; i++)
cout << C;
return 0;
}
B1037.在霍格沃兹找零钱 44min
自己做的又是结构体又是各种转换,太麻烦了。
究其原因是太依赖cout。直接用scanf可以直接识别.这个字符,就不用在那搞substr了。
/*B1036*/
#include <iostream>
#include <stdio.h>
#include <string>
#include <vector>
#include <algorithm>
#include <cctype>
#include <stack>
using namespace std;
struct Data {
int G;
int S;
int K;
};
Data Devide(string str)
{
int a, b,flag = 0;
for (int i = 0; i < str.length(); i++) //找到两个.的位置
{
if (str[i] == '.' && flag == 0)
{
a = i;
flag = 1;
}
if (str[i] == '.' && flag == 1)
b = i;
}
Data D;
D.G = stoi(str.substr(0, a));
D.S = stoi(str.substr(a + 1, b-a-1));
D.K = stoi(str.substr(b + 1, str.length()-b));
return D;
}
void Out(Data a, Data p)
{
stack<int> S;
if (a.K - p.K < 0)
{
S.push(a.K + 29 - p.K);
a.S--;
}
else
S.push(a.K - p.K);
if (a.S - p.S < 0)
{
S.push(a.S + 17 - p.S);
a.G--;
}
else
S.push(a.S - p.S);
S.push(a.G - p.G);
for (int i = 0; i < 3; i++)
{
cout << S.top();
S.pop();
if (i != 2) cout << '.';
}
}
int main()
{
string Pstr, Astr;
cin >> Pstr >> Astr;
Data p, a, tmp;
p = Devide(Pstr);
a = Devide(Astr);
if (p.G > a.G || (p.G == a.G && p.S > a.S)
|| (p.G == a.G && p.S == a.S && p.K > a.K))//如果应付大于实付
{
cout << '-';
Out(p, a);
}
else
Out(a, p);
return 0;
}
用scanf版本
/*B1036*/
#include <iostream>
#include <stdio.h>
#include <string>
#include <vector>
#include <algorithm>
#include <cctype>
#include <stack>
using namespace std;
int main()
{
int a, b, c, m, n, t;
scanf("%d.%d.%d %d.%d.%d", &a, &b, &c, &m, &n, &t);
if (a > m || (a == m && b > n) || (a == m && b == n && c > t))
{
swap(a, m);
swap(b, n);
swap(c, t);
printf("-"); //交换并加负号
}
int x, y, z;
z = t > c ? t - c : t + 29 - c;
n = t > c ? n : n - 1;//借位
y = n > b ? n - b : n + 17 - b;
m = n > b ? m : m - 1;
x = m - a;//上面的if已经排除了负数的情况
printf("%d.%d.%d",x,y,z);
return 0;
}
B1038.统计同成绩学生 9min
简单的hash表思想。
/*B1038*/
#include <iostream>
#include <stdio.h>
#include <string>
#include <vector>
#include <algorithm>
#include <cctype>
#include <stack>
using namespace std;
int main()
{
int N, K;
cin >> N;
int Score[101] = {0}; //0~100分
for (int i = 0; i < N; i++)
{
int score;
cin >> score;
Score[score]++;
}
cin >> K;
vector<int> vec;
for (int i = 0; i < K; i++)
{
int n;
cin >> n;
vec.push_back(n);
}
if (!vec.empty())
{
cout<<Score[vec[0]];
for (int i = 1; i < vec.size(); i++)
cout << " " << Score[vec[i]];
}
return 0;
}
B1039.到底买不买 27min
1.一开始想着用字符串处理做,比较麻烦。后来想到这题也可以用哈希表做。以后看到类似的优先考虑比较简便的哈希表。自己写个哈希函数把每个字符放到相应位置即可。
2.abs(int ) 取绝对值。
3.柳神的方法不用写哈希函数,比我的好
/*B1038*/
#include <iostream>
#include <stdio.h>
#include <string>
#include <vector>
#include <algorithm>
#include <cctype>
#include <stack>
using namespace std;
int HashFunction(char a)
{
if (a >= '0' && a <= '9')
return a - '0';
else if (islower(a))
return 10 + (a - 'a');
else if (isupper(a))
return 36 + (a - 'A');
}
int main()
{
string Have, Want;
cin >> Have >> Want;
int Hash[62] = {0};
for (int i = 0; i < Have.length(); i++)
{
Hash[HashFunction(Have[i])]++;//对应哈希表的位置加一
}
for (int i = 0; i < Want.length(); i++)
{
Hash[HashFunction(Want[i])]--;
}
int flag = 1,Psum = 0,Nsum = 0;//珠子够不够
for (int i = 0; i < 62; i++)
{
if (Hash[i] < 0)
{
flag = 0;
Nsum += Hash[i]; //所有负的加起来
}
else
{
Psum += Hash[i]; //正的都加起来
}
}
if (flag == 1)
cout << "Yes " << Psum;
else
cout << "No " << abs(Nsum);
return 0;
}
B1040.有几个PAT
自己做用了两层FOR,三个超时。思路和柳神一样都是先找A,然后找A前的P和A后的T,将两者数量相乘。
但柳神利用for之前T无效的特性,一个FOR遇到A就计算一次,来解决问题的。
要注意cnt输出那里,一定要计算for的算式中取余。否则乘积太大会溢出导致结果错误。
/*B1040*/
#include <iostream>
#include <stdio.h>
#include <string>
#include <vector>
#include <algorithm>
#include <cctype>
#include <stack>
using namespace std;
const int Xnum = 1000000007;
int main()
{
string str;
cin >> str;
int cnt = 0;
vector<int> P;
vector<int> A;
vector<int> T;
for (int i = 0; i < str.length(); i++)
{
if (str[i] == 'P') P.push_back(i);
if (str[i] == 'A') A.push_back(i);
if (str[i] == 'T') T.push_back(i);
}
for(int i = 0;i<A.size();i++)
{
int n = 0, m = 0;
for (int j = 0; j < P.size(); j++)
{
if (P[j] < A[i]) n++;
}
for (int j = 0; j < T.size(); j++)
{
if (T[j] > A[i]) m++;
}
cnt += n*m;
}
cout << cnt%Xnum;
return 0;
}
/*B1040*/
#include <iostream>
#include <stdio.h>
#include <string>
#include <vector>
#include <algorithm>
#include <cctype>
#include <stack>
using namespace std;
const int Xnum = 1000000007;
int main()
{
string str;
cin >> str;
int cnt = 0;
int countp = 0, countt = 0;
for (int i = 0; i < str.length(); i++)
if(str[i] == 'T') countt++;
for (int i = 0; i < str.length(); i++)
{
if (str[i] == 'T') countt--; //在A之前的T无效
if (str[i] == 'P') countp++;
if (str[i] == 'A')
cnt = (cnt + (countp * countt)%Xnum ) %Xnum;
}
cout << cnt%Xnum;
return 0;
}
B1041.考试座位号 8min
签到题
/*B1041*/
#include <iostream>
#include <stdio.h>
#include <string>
#include <vector>
#include <algorithm>
#include <cctype>
#include <stack>
using namespace std;
struct Seat
{
string ID;
int seat;
};
Seat List[1000];
int main()
{
int N;
cin >> N;
for (int i = 0; i < N; i++)
{
string ID;
int test, seat;
cin >> ID >> test >> seat;
List[test].ID = ID;
List[test].seat = seat;
}
int M;
cin >> M;
for (int i = 0; i < M; i++)
{
int check;
cin >> check;
cout << List[check].ID << " " << List[check].seat << "\n";
}
return 0;
}
B1042.字符统计 22min
思路很简单,一开始用cin卡了一下,忘记只读入两个空格之间的字符串了,所以要用while把他们连起来。
用geiline(cin ,str)更容易,而且在VS上可以调试。
/*B1041*/
#include <iostream>
#include <stdio.h>
#include <string>
#include <vector>
#include <algorithm>
#include <cctype>
#include <stack>
using namespace std;
int HashFunc( char a)
{
if (islower(a)) return (a - 'a');
else if (isupper(a)) return (a - 'A');
}
int main()
{
string str,tmp;
while (cin >> tmp) //getline(cin,str);
str += tmp;
int List[26] = {0};
for (int i = 0; i < str.length(); i++)
{
if (isalpha(str[i]))
List[HashFunc(str[i])] ++;
}
int MaxA, Maxn = 0;
for (int i = 0; i < 26; i++)
{
if (List[i] > Maxn)
{
MaxA = i;
Maxn = List[i];
}
}
char result = 'a' + MaxA;
cout << result << " "<<List[MaxA];
return 0;
}
B1043.输出PTAest 24min
我自己是做了一个哈希函数,柳神则是直接粗暴用了一个128大小的数组直接充当哈希表存放。
然后她用了一个while输出,比我的逻辑简单。
我的版本:
/*B1041*/
#include <iostream>
#include <stdio.h>
#include <string>
#include <vector>
#include <algorithm>
#include <cctype>
#include <stack>
using namespace std;
int HashFunc(char a)
{
if (a == 'P') return 0;
else if (a == 'A') return 1;
else if (a == 'T') return 2;
else if (a == 'e') return 3;
else if (a == 's') return 4;
else if (a == 't') return 5;
else
return -1;
}
int main()
{
string str;
cin >> str;
int List[6] = {0};
char Alpha[6] = { 'P','A','T','e','s','t' };
for(int i =0;i<str.length();i++)
{
int tmp = HashFunc(str[i]);
if (tmp >= 0)
List[tmp]++;
}
int flag = 1;
while (flag == 1)
{
int zerocnt = 0;//初始化本轮为0的格子数
for (int i = 0; i < 6; i++)
{
if (List[i] != 0)
{
cout << Alpha[i];
List[i]--;
}
else
zerocnt++;//为0的格子数量加一
}
if (zerocnt == 6) flag = 0;//6个格子都是0则改变flag
}
return 0;
}
B1044.火星数字 51min
做本题被难住了,主要是那个低位的0的问题,在火星文翻译回十进制时如果恰好是13 的倍数则不用输出低位的0,在规定时间内只拿了两分。
思路不难,主要是要理解准确题意。
/*B1041*/
#include <iostream>
#include <stdio.h>
#include <string>
#include <vector>
#include <algorithm>
#include <cctype>
#include <stack>
using namespace std;
string Low[13] = { "tret","jan", "feb", "mar", "apr", "may",
"jun", "jly", "aug", "sep", "oct", "nov", "dec" };
string High[12] = { "tam", "hel", "maa", "huh", "tou", "kes",
"hei", "elo", "syy", "lok", "mer", "jou" };
void MarsToEarth(string str)
{
if (str.length() < 4)//只有低位or只有高位
{
for (int i = 0; i < 13; i++)
{
if (Low[i] == str) cout << i<<"\n";
}
for (int i = 0; i < 12; i++)
{
if (High[i] == str) cout << (i+1) *13 << "\n";
}
}
else //有高位有低位
{
string high, low;
int h, l;
high = str.substr(0, 3);
low = str.substr(4, 3);
for (int i = 0; i < 13; i++)
{
if (Low[i] == low) l = i;
}
for (int j = 0; j < 12; j++)
{
if (High[j] == high) h = j +1;
}
cout<< h * 13 + l;
}
}
void EarthToMars(int n)
{
if (n / 13) cout << High[n / 13 -1];
if ((n / 13) && (n % 13)) cout << " ";
if ((n % 13) || n == 0) cout << Low[n % 13];
}
int main()
{
int N;
cin >> N;
getchar();
for (int i = 0; i < N; i++)
{
string str;
getline(cin, str);
if (isalpha(str[0]))
MarsToEarth(str);
else if(isalnum(str[0]))
EarthToMars(stoi(str));
cout << endl;
}
return 0;
}
B1045.快速排序 29Min
自己做的时候做出两个超时点,我是用指针一个个去指向左右来做的。
柳神的方法是利用了一个难以察觉的性质:当某个数的左边全比这个数大的时候,这个数的在数组中的排序也一定不会变。
所以就制造两个数组,其中一个是原始输入序列,另一个是排序后的序列。当某个元素的位置没有发生变化且左边所有值的最大值都比这个元素小的时候就可以认为是主元了。所以只要N复杂度。
我的版本:两个超时(复杂度N的平方)
/*B1045*/
#include <iostream>
#include <stdio.h>
#include <string>
#include <vector>
#include <algorithm>
#include <cctype>
#include <stack>
using namespace std;
int main()
{
int N;
cin >> N;
vector<int> vec;
for (int i = 0; i < N; i++)
{
int num;
cin >> num;
vec.push_back(num);
}
vector<int> result;
for (int i = 0; i < N; i++)
{
int j = i;
int L = 1,R = 1;
if (j > 0) //左边
{
for (; j >= 0; j--)
if (vec[j] > vec[i]) {
L = 0;
break;
}
}
j = i; //回正指针
if (j < N - 1 && L ==1)//右边..左边不符合右边没必要看
{
for (; j <= N - 1; j++)
if (vec[j] < vec[i]) {
R = 0;
break;
}
}
if (L && R)
result.push_back(vec[i]);
}
sort(result.begin(), result.end());
cout << result.size() << "\n";
if (!result.empty()) cout << result[0];
for (int i = 1; i < result.size(); i++)
{
cout << " " << result[i];
}
cout << "\n";
return 0;
}
本文记录了作者在刷PAT乙级题目过程中遇到的问题和解决方法,涉及字符串操作、数据结构、算法优化等方面,包括四舍五入的实现、沙漏打印、人口普查的高效解决方案等,并对比了自己与他人代码的差异,强调了哈希表、递归、辗转相除法等在解题中的应用。
615

被折叠的 条评论
为什么被折叠?



