(PAT乙级题目练习 持续更新~)
文章目录
1003.“答案正确”自动判题系统-----我要通过!(使用map)
问题描述:
“答案正确”是自动判题系统给出的最令人欢喜的回复。本题属于 PAT 的“答案正确”大派送 —— 只要读入的字符串满足下列条件,系统就输出“答案正确”,否则输出“答案错误”。
得到“答案正确”的条件是:
字符串中必须仅有 P、 A、 T这三种字符,不可以包含其它字符;
任意形如 xPATx 的字符串都可以获得“答案正确”,其中 x 或者是空字符串,或者是仅由字母 A 组成的字符串;
如果 aPbTc 是正确的,那么 aPbATca 也是正确的,其中 a、 b、 c 均或者是空字符串,或者是仅由字母 A 组成的字符串。
现在就请你为 PAT 写一个自动裁判程序,判定哪些字符串是可以获得“答案正确”的。
输入格式:
每个测试输入包含 1 个测试用例。第 1 行给出一个正整数 n (<10),是需要检测的字符串个数。接下来每个字符串占一行,字符串长度不超过 100,且不包含空格。
9
PAT
PAAT
AAPATAA
AAPAATAAAA
xPATx
PT
Whatever
APAAATAA
APT
输出格式:
每个字符串的检测结果占一行,如果该字符串可以获得“答案正确”,则输出
YES
YES
YES
YES
NO
NO
NO
NO
NO
解题思路:
任意形如 xPATx 的字符串都可以获得“答案正确”,其中 x 或者是空字符串,或者是仅由字母 A 组成的字符串;
那么正确的有这些:
PAT
APATA
AAPATAA
AAAPATAAA
就是中间一个A左右加上等量的A(不加也行)都是正确的。
如果 aPbTc 是正确的,那么 aPbATca 也是正确的,其中 a, b, c 均或者是空字符串,或者是仅由字母 A 组成的字符串。
拿上面的那几个正确的举例子,那么正确的有这些:
PAT —— 对于 aPbTc 来说ac是空,b是A。所以 PAAT 是正确的。同理PAAAAAT中间加多少个A都是正确哒~
APATA —— 对于aPbTc来说,abc都是A。所以 APAATAA 是正确的。再类推一下,那么 APAAATAAA 是正确的。
AAPATAA —— 对于aPbTc来说,a和c是AA,b是A。所以AAPAATAAAA是正确的,再类推一下,AAPAAATAAAAAA 是正确的~
所以说规律就是,可以在P和T中间加A并且在T后面加A,要求必须是,中间加上一个A,末尾就得加上几倍的(P前面A的那个字符串)。换句话说就是,中间的A的个数如果是3,那么末尾的A的个数就得是开头A的个数的3倍。很巧,当中间A为一个的时候,末尾和开头A的个数必须相等正好是第二条的要求
所以一句话总结字符串的要求:只能有一个P一个T,中间末尾和开头可以随便插入A。但是必须满足开头的A的个数 * 中间的A的个数 = 结尾的A的个数,而且P和T之间不能没有A~
代码实现:
- 常规方法
#include <iostream>
#include <string.h>
using namespace std;
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
bool flag=1;
char a[100];
int posp=0,post=0,nump=0,numt=0;
cin>>a;
for(int j=0;j<strlen(a);j++){
if((a[j]!='P')&&a[j]!='T'&&a[j]!='A') {flag=0;break;}
if(a[j]=='P') {posp=j;nump++;}
if(a[j]=='T') {post=j;numt++;}
}
if(nump!=1||numt!=1||(post-posp)==1||posp*(post-posp-1)!=(strlen(a)-post-1))
flag=0;
if(flag) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}
2.map实现
C++map用法总结https://blog.youkuaiyun.com/sevenjoin/article/details/81943864
#include <iostream>
#include <map>
using namespace std;
int main(){
int n,p,t;
string s;
cin>>n;
for(int i=0;i<n;i++){
cin>>s;
map<char,int> m;
for(int j=0;j<s.size();j++){
m[s[j]]++;
if(s[j]=='P') p=j;
if(s[j]=='T') t=j;
}
if(m['P']==1&&m['T']==1&&t-p>1&&p*(t-p-1)==s.size()-t-1&&m.size()==3)
cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}
1004.成绩排名
读入 n(>0)名学生的姓名、学号、成绩,分别输出成绩最高和成绩最低学生的姓名和学号。
输入格式:
每个测试输入包含 1 个测试用例,格式为
第 1 行:正整数 n
第 2 行:第 1 个学生的姓名 学号 成绩
第 3 行:第 2 个学生的姓名 学号 成绩
… … …
第 n+1 行:第 n 个学生的姓名 学号 成绩
其中姓名和学号均为不超过 10 个字符的字符串,成绩为 0 到 100 之间的一个整数,这里保证在一组测试用例中没有两个学生的成绩是相同的。
输出格式:
对每个测试用例输出 2 行,第 1 行是成绩最高学生的姓名和学号,第 2 行是成绩最低学生的姓名和学号,字符串间有 1 空格。
输入样例:
3
Joe Math990112 89
Mike CS991301 100
Mary EE990830 95
输出样例:
Mike CS991301
Joe Math990112
解题思路
这题我没有什么巧妙地方法,就是打擂台方法。
代码实现
- 常规
#include <iostream>
#include <string>
using namespace std;
int main(){
int n,score,mscore,iscore;
string name,id,mname,iname,mid,iid;
cin>>n;
for(int i=0;i<n;i++){
cin>>name>>id>>score;
if(i==0) {
mscore=score;
mname=name;
mid=id;
iscore=score;
iname=name;
iid=id;
}
else {
if(score>mscore) {
mscore=score;
mname=name;
mid=id;
}
if(score<iscore) {
iscore=score;
iname=name;
iid=id;
}
}
}
cout<<mname<<" "<<mid<<endl;
cout<<iname<<" "<<iid<<endl;
return 0;
}
- 结构体(没有想到)
#include <iostream>
using namespace std;
struct Student{
string name;
string number;
int score;
};
int main()
{
int n;
cin>>n;
Student *s = new Student[n];
int smin=100,smax=0;
int sminnum,smaxnum;
for(int i=0;i<n;i++){
cin>>s[i].name>>s[i].number>>s[i].score;
if(s[i].score<smin){smin=s[i].score; sminnum=i;}
if(s[i].score>smax){smax=s[i].score; smaxnum=i;}
}
cout<<s[smaxnum].name<<" "<<s[smaxnum].number<<endl;
cout<<s[sminnum].name<<" "<<s[sminnum].number<<endl;
return 0;
}
1005.继续(3n+1)猜想 (25分) (使用vector)
卡拉兹(Callatz)猜想已经在1001中给出了描述。在这个题目里,情况稍微有些复杂.当我们验证卡拉兹猜想的时候,为了避免重复计算,可以记录下递推过程中遇到的每一个数。例如对 n=3 进行验证的时候,我们需要计算 3、5、8、4、2、1,则当我们对 n=5、8、4、2 进行验证的时候,就可以直接判定卡拉兹猜想的真伪,而不需要重复计算,因为这 4 个数已经在验证3的时候遇到过了,我们称 5、8、4、2 是被 3“覆盖”的数。我们称一个数列中的某个数 n为“关键数”,如果 n 不能被数列中的其他数字所覆盖。
现在给定一系列待验证的数字,我们只需要验证其中的几个关键数,就可以不必再重复验证余下的数字。你的任务就是找出这些关键数字,并按从大到小的顺序输出它们。
输入格式:
每个测试输入包含 1 个测试用例,第 1 行给出一个正整数 K (<100),第 2 行给出 K 个互不相同的待验证的正整数 n (1<n≤100)的值,数字间用空格隔开。
输出格式:
每个测试用例的输出占一行,按从大到小的顺序输出关键数字。数字间用 1 个空格隔开,但一行中最后一个数字后没有空格。
输入样例:
6
3 5 6 7 8 11
输出样例:
7 6
解题思路
使用一个很大的数组b(长度10000),初始均为false 。以n=3 进行验证的时候,我们需要计算 3、5、8、4、2、1,则数组中b[5]=true表示被覆盖。同理,b[8]=true、b[4]=true、b[2]=true也表示被覆盖。遍历数组,若b[i]=false,则为关键数。
代码实现
- 数组:
#include <iostream>
#include <algorithm>
using namespace std;
bool cmp(int a,int b)
{
return a>b;
}
int main(){
int i,n,a[100],num;
bool b[10000*3+1]={0};
cin>>n;
for(i=0;i<n;i++){
cin>>num;
a[i]=num;
while(num!=1){
if(num%2==0) {num=num/2; b[num]=1;
}
else {num=(3*num+1)/2; b[num]=1;
}
}
sort(a,a+n,cmp);
}
int flag=0;
for(int z=0;z<n;z++){
if(b[a[z]]==0) {
if(flag) cout<<" ";
cout<<a[z];
flag=1;
}
}
}
- 使用vector (思路和数组一样,排序的时候方便一点)
#include<iostream>
#include<vector>
#include<algorithm>
#define MAX 10000
using namespace std;
bool num[3 * MAX + 1];
int main(void) {
int n, data;
vector<int> v;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> data;
v.push_back(data);
while (data != 1) {
if (data % 2)
data = (3 * data + 1) / 2;
else
data /= 2;
num[data] = true;
}
}
sort(v.begin(), v.end());
reverse(v.begin(), v.end());
int flag = 0;
for (int i = 0; i < v.size(); i++)
if (num[v[i]] == false) {
if (flag)
cout << " ";
cout << v[i];
flag = 1;
}
}
1006.换个格式输出整数
让我们用字母 B 来表示“百”、字母 S 表示“十”,用 12…n 来表示不为零的个位数字 n(<10),换个格式来输出任一个不超过 3 位的正整数。例如 234 应该被输出为 BBSSS1234,因为它有 2 个“百”、3 个“十”、以及个位的 4。
输入格式:
每个测试输入包含 1 个测试用例,给出正整数 n(<1000)。
输出格式:
每个测试用例的输出占一行,用规定的格式输出 n。
输入样例 1:
234
输出样例 1:
BBSSS1234
解题思路
由于题目只说了n<1000,所以直接暴力解
代码实现:
#include <iostream>
using namespace std;
int main(){
int n,b,s,g;
cin>>n;
g=n%10;
n=n/10;
s=n%10;
n=n/10;
b=n%10;
for(int i=1;i<=b;i++){
cout<<"B";
}
for(int i=1;i<=s;i++){
cout<<"S";
}
for(int i=1;i<=g;i++){
cout<<i;
}
}
1007 素数对猜想
输入格式:
输入在一行给出正整数N。
输出格式:
在一行中输出不超过N的满足猜想的素数对的个数。
输入样例:20
输出样例:
4
解题思路
- 先把素数表写道一个数组里,然后遍历数组,若a[z+1]-a[z]==2,则计数器num++
- 大佬方法: 判断素数的函数isprime这样写:对于数字a,i从2到根号a,如果a能够被其中⼀个i整除,说明i
不是素数,return false,否则说明a是素数return true;对于输⼊数据N,for循环中的i从5到N依次判断
i-2和i是否是素数,如果都是素数,则统计个数的cnt++,最后输出cnt即可~
实现代码
- 我的实现方法
#include <iostream>
#include <math.h>
using namespace std;
int main(){
int n,i,j,k=0,a[100000];
cin>>n;
for(int i=2;i<=n;i++){
for( j=2;j<=sqrt(i);j++)
{
if(i%j==0) break;
}
if(j>sqrt(i)){
a[k++]=i;
}
}
int num=0;
for(int z=0;z<k-1;z++)
{
if(a[z+1]-a[z]==2)
num++;
}
cout<<num;
}
2.大佬方法:
#include <iostream>
using namespace std;
bool isprime(int a) {
for (int i = 2; i * i <= a; i++)
if (a % i == 0) return false;
return true; }
int main() {
int N, cnt = 0;
cin >> N;
for (int i = 5; i <= N; i++)
if (isprime(i-2) && isprime(i)) cnt++;
cout << cnt;
return 0; }
1008 数组元素循环右移问题 (使用vector)
输入格式:
每个输入包含一个测试用例,第1行输入N(1≤N≤100)和M(≥0);第2行输入N个整数,之间用空格分隔。
输出格式:
在一行中输出循环右移M位以后的整数序列,之间用空格分隔,序列结尾不能有多余空格。
输入样例:6 2 1 2 3 4 5 6
输出样例:
5 6 1 2 3 4
解题思路:
用vector实现
数组⻓度为n,要想把数组循环右移m位,只需要先将整个数组a倒置,再将数组前m位倒置,最后将数组后n-m位倒置即可完成循环右移m位~reverse函数可以实现将⼀个数组或者vector中元素倒置,这个函数在algorithm头⽂件中~
(如果m⼤于n,那么循环右移m位相当于循环右移m%n位,因为那些n倍数位的移动是多余的,所以在使⽤m之前,先将m = m%n)
代码实现:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main(){
int n,m,num;
cin>>n>>m;
vector<int> v;
for(int i=0;i<n;i++)
{
cin>>num;
v.push_back(num);
}
m=m%n;
if(m){
reverse(v.begin(),v.end());
reverse(v.begin(),v.begin()+m);
reverse(v.begin()+m,v.end());
}
for(int i=0;i<n;i++){
if(i!=0) cout<<" ";
cout<<v[i];
}
return 0;
}
1009 说反话 (用stack)
给定一句英语,要求你编写程序,将句中所有单词的顺序颠倒输出。
输入格式:
测试输入包含一个测试用例,在一行内给出总长度不超过 80 的字符串。字符串由若干单词和若干空格组成,其中单词是由英文字母(大小写有区分)组成的字符串,单词之间用 1 个空格分开,输入保证句子末尾没有多余的空格。
输出格式:
每个测试用例的输出占一行,输出倒序后的句子。
输入样例:Hello World Here I Come
输出样例:
Come I Here World Hello
解题思路:
使用栈:
将输⼊的每个单词s都分别v.push(s)压⼊栈中,再输出栈顶v.top(),然后将栈顶元素弹出
v.pop(),直到栈空为⽌~
实现代码:
#include <iostream>
#include <stack>
using namespace std;
int main(){
stack<string> v;
string s;
while(cin>>s) v.push(s);
cout<<v.top();
v.pop();
while(!v.empty()) {
cout<<" "<<v.top();
v.pop();
}
}
1010 一元多项式求导(flag的妙用)
设计函数求一元多项式的导数。
输入格式:
以指数递降方式输入多项式非零项系数和指数(绝对值均为不超过 1000 的整数)。数字间以空格分隔。
输出格式:
以与输入相同的格式输出导数多项式非零项的系数和指数。数字间以空格分隔,但结尾不能有多余空格。注意“零多项式”的指数和系数都是 0,但是表示为 0 0。
输入样例:3 4 -5 2 6 1 -2 0
输出样例:
12 3 -10 1 6 0
解题思路:
- flag⽤来判断是否已经有过输出~
- 当b!=0时,因为给出的是所有⾮零项系数,所以必定会有输出,先判断flag是否为1,如果为1表示已经有过输出,那么在前⾯要先输出⼀个空格
- 输出 a * b 和 b – 1,然后将flag标记为1表示已经有过输出
- 最后判断当没有输出并且b==0的时候,输出“0 0”
代码实现:
#include <iostream>
using namespace std;
int main() {
int a,b,flag=0;
while(cin>>a>>b){
if(b!=0){
if(flag==1) cout<<" ";
cout<<a*b<<" "<<b-1;
flag=1;
}
}
if(flag==0) cout<<"0 0";
}
1011 A+B 和 C (long long永远滴神)
输入格式:
输入第 1 行给出正整数 T (≤10),是测试用例的个数。随后给出 T 组测试用例,每组占一行,顺序给出 A、B 和 C。整数间以空格分隔。
输出格式:
对每组测试用例,在一行中输出 Case #X: true 如果 A+B>C,否则输出 Case #X: false,其中 X 是测试用例的编号(从 1 开始)。
输入样例:4 1 2 3 2 3 4 2147483647 0 2147483646 0 -2147483648 -2147483647
输出样例:
Case #1: false Case #2: true Case #3: true Case #4: false
解题思路:
使⽤long long int存储a、b和c,直接盘它~
实现代码:
#include<iostream>
using namespace std;
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++){
long long int a,b,c;
cin>>a>>b>>c;
if(a+b>c) cout<<"Case #"<<i+1<<": true";
else cout<<"Case #"<<i+1<<": false";
cout<<endl;
}
}
1012 数字分类 (限制小数点位数)
给定一系列正整数,请按要求对数字进行分类,并输出以下 5 个数字:
- A1= 能被 5 整除的数字中所有偶数的和;
- A2= 将被 5 除后余 1 的数字按给出顺序进行交错求和,即计算
n1−n2+n3−n4⋯;- A3= 被 5 除后余 2 的数字的个数;
- A4= 被 5 除后余 3 的数字的平均数,精确到小数点后1位;
- A5= 被 5 除后余 4 的数字中最大数字。
输入格式:
每个输入包含 1 个测试用例。每个测试用例先给出一个不超过 1000 的正整数 N,随后给出 N 个不超过 1000 的待分类的正整数。数字间以空格分隔。
输出格式:
对给定的 N 个正整数,按题目要求计算 A1~A5
并在一行中顺序输出。数字间以空格分隔,但行末不得有多余空格。
若其中某一类数字不存在,则在相应位置输出 N。
输入样例 1:
13 1 2 3 4 5 6 7 8 9 10 20 16 18
输出样例 1:
30 11 2 9.7 9
输入样例 2:
8 1 2 4 5 6 7 9 16
输出样例 2:
N 11 2 N 9
解题思路:
- 对cin中的每⼀个元素num按照不同分类计算出A1 A2…A5~ 因为只有五类数,直接分类输出就好了
- 注意 A2 交错求和的结果也可能等于 0 ,此时不能输出 N(测试点8)
解决办法: 用个flag=0, 只要更改过A2,把flag改为1,输出的时候加个条件就可以啦~
实现代码:
#include<iostream>
#include<iomanip>
using namespace std;
int main()
{
int n,a=1,b=1,flag=0,A1=0,A2=0,A3=0,A5=0;
double A4=0.0; double sum=0.0;
cin>>n;
for(int i=0;i<n;i++){
int num;
cin>>num;
if(num%5==0&&num%2==0) A1+=num;
if(num%5==1) {A2+=num*a; a=-a; flag=1;}
if(num%5==2) A3++;
if(num%5==3) {sum=sum+num; A4=sum/(b++);}
if(num%5==4) {if(num>A5) A5=num;}
}
if(A1==0) cout<<"N "; else cout<<A1<<" ";
if(A2==0&&flag==0) cout<<"N "; else cout<<A2<<" ";
if(A3==0) cout<<"N "; else cout<<A3<<" ";
if(A4==0) cout<<"N ";else cout<<fixed<<setprecision(1)<<A4<<" ";
if(A5==0) cout<<"N"; else cout<<A5;
}
1013 数素数 (素数 控制每行10个)
输入格式:5 27
输出样例:
11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103
解题思路
实现代码
#include<iostream>
#include<vector>
using namespace std;
bool f(int x){
for(int i=2;i*i<=x;i++)
if(x%i==0) return false;
return true;
}
int main()
{
int m,n,t=0,flag=0;
vector<int> v;
cin>>m>>n;
for(int i=2;t<n;i++)
{
if(f(i)) {t++; if(t>=m) v.push_back(i);}
}
t=0;
for(int i=0;i<n-m+1;i++){
t++;
if(flag!=0) cout<<" ";
cout<<v[i];
flag=1;
if(t%10==0) {
cout<<"\n";
flag=0;
}
}
}
1014
输入样例:3485djDkxh4hhGE 2984akDfkkkkggEdsb s&hgsfdk d&Hyscvnm