PAT(乙级) 题目1001-1010
2023.1.24 ☁very cold!!😊
1001 害死人不偿命的(3n+1)猜想(√)
卡拉兹(Callatz)猜想:
对任何一个正整数 n,如果它是偶数,那么把它砍掉一半;如果它是奇数,那么把 (3n+1) 砍掉一半。这样一直反复砍下去,最后一定在某一步得到 n=1。卡拉兹在 1950 年的世界数学家大会上公布了这个猜想,传说当时耶鲁大学师生齐动员,拼命想证明这个貌似很傻很天真的命题,结果闹得学生们无心学业,一心只证 (3n+1),以至于有人说这是一个阴谋,卡拉兹是在蓄意延缓美国数学界教学与科研的进展……
我们今天的题目不是证明卡拉兹猜想,而是对给定的任一不超过 1000 的正整数 n,简单地数一下,需要多少步(砍几下)才能得到 n=1?
输入格式:
每个测试输入包含 1 个测试用例,即给出正整数 n 的值。
输出格式:
输出从 n 计算到 1 需要的步数。
输入样例:
3
输出样例:
5
思路:判断奇偶数,进行相应操作
代码如下:
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
cin>>n;
int pos = 0;
while(n!=1){
if(n%2 == 0){ //为偶数时
n = n/2;
}
else{
n = (3*n+1)/2;
}
pos++;
}
cout<<pos;
return 0;
}
①3n要写成3*n
进行算数运算时,不能出现3n+1,否则会报错:[Error] invalid suffix "n" on integer constant
n = (3*n+1)/2;
1002 写出这个数(√)
读入一个正整数 n,计算其各位数字之和,用汉语拼音写出和的每一位数字。
输入格式:
每个测试输入包含 1 个测试用例,即给出自然数 n 的值。这里保证 n 小于 10^100 。
输出格式:
在一行内输出 n 的各位数字之和的每一位,拼音数字间有 1 空格,但一行中最后一个拼音数字后没有空格。
输入样例:
1234567890987654321123456789
输出样例:
yi san wu
代码如下:
#include<bits/stdc++.h>
using namespace std;
int arr[1000]; //存储算得的结果的各位数
int main(){
char n[101];
cin>>n;
char han[10][5] = {"ling","yi","er","san","si","wu","liu","qi","ba","jiu"};
int pos = strlen(n); //表示该数有几位
int ans = 0;
for(int i=0; i<pos; i++){ //计算得到各位数之和
ans = ans + n[i] - '0';
//cout<<ans<<" ";
}
int x = 0; //表示所得答案有几位
while(ans != 0){ //将答案的各位数存入数组
arr[x] = ans%10;
x++;
ans = ans/10;
}
for(int i=x-1; i>=0; i--){
cout<<han[arr[i]];
if(i!=0) cout<<" ";
}
return 0;
}
只能小数通过(T-T,我好像只能自己写成这样,先放这吧,想让小赵老师给我改一改,以后有时间再说吧)(++自己改出来啦!!!happy!!!虽然捣鼓了很久嘿嘿:
int main(){
int n;
cin>>n;
char han[10][5] = {"ling","yi","er","san","si","wu","liu","qi","ba","jiu"};
int pos = 0; //表示该数有几位
while(n != 0){ //将各位数存入数组
arr[pos] = n%10;
pos++;
n = n/10;
}
int ans = 0;
for(long long i=0; i<pos; i++){ //计算得到各位数之和
ans = ans + arr[i];
}
int x = 0; //表示所得答案有几位
while(ans != 0){ //将答案的各位数存入数组
a[x] = ans%10;
x++;
ans = ans/10;
}
for(long long i=x-1; i>=0; i--){
cout<<han[a[i]]<<" ";
}
return 0;
}
①字符串数组的定义
定义字符串数组的时候,出现报错:[Error] too many initializers for 'char [10]'
char数组,一个字符串相当于一个一维的字符数组,此时字符数组的长度就是字符串的长度,多个字符串就意味着多了一个“一维数组”但这个数组里保存的是字符串,所以集合成了字符二维数组。该二维数组行定义的时候就表示字符串的个数(适当加大点容量,防止有可能发生的段错误),列是字符串的长度。
因为字符串是字面值,即常量,应该这样声明数组:
const char* numbers[] = {"ling","yi","er","san","si","wu","liu","qi","ba","jiu"};
也可以这样声明数组:
char numbers[10][5] = {"ling","yi","er","san","si","wu","liu","qi","ba","jiu"};
它所做的是声明一个包含 9 个元素的二维数组,每个元素包含 6 个字符。所以现在您可以根据需要在运行时更改每个单词的值。
while(ans != 0){ //将计算所得结果各位数存入数组
int x = i;
array[x] = ans%10;
x--;
ans = ans/10;
}
for(int j=i; j>i; j--){
cout<<han[array[j]]<<" ";
}
②用char来表示自然数
输入要求,是一个自然数,且不超过101位,这个数过大,超过了int、long long的范围,只能通过char来定义
char n[101];
cin>>n;
③数据类型转换
在计算时把字符型数据转换为整型,加 - ‘0’
ans = ans + n[i] - '0';
2023.1.25 ☁ cold!!😯
1003 我要通过!
“答案正确”是自动判题系统给出的最令人欢喜的回复。本题属于 PAT 的“答案正确”大派送 —— 只要读入的字符串满足下列条件,系统就输出“答案正确”,否则输出“答案错误”。
得到“答案正确”的条件是:
字符串中必须仅有 P、 A、 T这三种字符,不可以包含其它字符;
任意形如 xPATx 的字符串都可以获得“答案正确”,其中 x 或者是空字符串,或者是仅由字母 A 组成的字符串;
如果 aPbTc 是正确的,那么 aPbATca 也是正确的,其中 a、 b、 c 均或者是空字符串,或者是仅由字母 A 组成的字符串。
现在就请你为 PAT 写一个自动裁判程序,判定哪些字符串是可以获得“答案正确”的。
输入格式:
每个测试输入包含 1 个测试用例。第 1 行给出一个正整数 n (≤10),是需要检测的字符串个数。接下来每个字符串占一行,字符串长度不超过 100,且不包含空格。
输出格式:
每个字符串的检测结果占一行,如果该字符串可以获得“答案正确”,则输出 YES,否则输出 NO。
输入样例:
10
PAT
PAAT
AAPATAA
AAPAATAAAA
xPATx
PT
Whatever
APAAATAA
APT
APATTAA
输出样例:
YES
YES
YES
YES
NO
NO
NO
NO
NO
NO
代码如下:
在这里插入代码片
不会写,😅
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
思路:
定义一个结构体,包含姓名、学号、分数
头文件有点疑惑。
解决啦!
万能头文件里包含了algorithm文件,max和min是其中的一个函数,所以运行报错。
代码如下:
#include<stdio.h>
struct student
{
char name[15];
char ID[15];
int grade;
}temp,max,min; //全局变量
int main(){
int n;
scanf("%d",&n);
max.grade = -1;
min.grade = 101;
while(n--){
scanf("%s %s %d",&temp.name, &temp.ID, &temp.grade);
if(temp.grade > max.grade){
max = temp;
}
if(temp.grade < min.grade){
min = temp;
}
}
printf("%s %s\n",&max.name, &max.ID);
printf("%s %s",&min.name, &min.ID);
return 0;
}
C++代码如下:
#include<bits/stdc++.h>
using namespace std;
struct student
{
char name[15];
char ID[15];
int grade;
}temp,da,xiao; //全局变量
int main(){
int n;
cin>>n;
da.grade = -1;
xiao.grade = 101;
while(n--){
//scanf("%s %s %d",&temp.name, &temp.ID, &temp.grade);
cin>>temp.name>>temp.ID>>temp.grade;
if(temp.grade > da.grade){
da = temp;
}
if(temp.grade < xiao.grade){
xiao = temp;
}
}
//printf("%s %s\n",&da.name, &da.ID);
//printf("%s %s",&xiao.name, &xiao.ID);
cout<<da.name<<" "<<da.ID<<endl;
cout<<xiao.name<<" "<<xiao.ID;
return 0;
}
1005 继续(3n+1)猜想
卡拉兹(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
不会写…
在这里插入代码片
1006 换个格式输出整数(√)
让我们用字母 B 来表示“百”、字母 S 表示“十”,用 12…n 来表示不为零的个位数字 n(<10),换个格式来输出任一个不超过 3 位的正整数。例如 234 应该被输出为 BBSSS1234,因为它有 2 个“百”、3 个“十”、以及个位的 4。
输入格式:
每个测试输入包含 1 个测试用例,给出正整数 n(<1000)。
输出格式:
每个测试用例的输出占一行,用规定的格式输出 n。
输入样例 1:
234
输出样例 1:
BBSSS1234
输入样例 2:
23
输出样例 2:
SS123
代码如下:
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
cin>>n;
int ge = n % 10;
n = n/10;
int shi = n%10;
n = n/10;
int bai = n%10;
while(bai--){
cout<<"B";
}
while(shi--){
cout<<"S";
}
for(int i=1; i<=ge; i++){
cout<<i;
}
return 0;
}
1007 素数对猜想(√)
代码如下:
#include<bits/stdc++.h>
using namespace std;
bool is_prime(int x){
for(int i=2; i*i<=x; i++){
if(x%i == 0) return 0;
}
if(x<=2) return 0;
return 1;
}
bool is_primepair(int x){
if(is_prime(x)){
if(is_prime(x+2)) return 1;
else return 0;
}
else return 0;
}
int main(){
int n;
scanf("%d", &n);
int ans = 0;
for(int i=1; i+2<=n; i++){ //判断条件注意i+2<=n
if(is_primepair(i)) ans++;
}
printf("%d", ans);
return 0;
}
1008 数组元素循环右移问题(√)
思路:
放入数组中
知道是循环即可,可以不进行处理,直接将所有数输出。
!M是有可能大于N的,所以需要对M模N
代码如下:
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,m;
cin>>n>>m;
m = m % n;
int a[100];
for(int i=0; i<n; i++){
cin>>a[i];
}
int count = 0;
for(int i=n-m; i<n; i++){
cout<<a[i];
count = count + 1;
if(count<n) cout<<" ";
}
for(int i=0; i<n-m; i++){
cout<<a[i];
count = count + 1;
if(count<n) cout<<" ";
}
return 0;
}
不满分代码:输出空格存在问题
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,m;
cin>>n>>m;
int a[100];
for(int i=0; i<n; i++){
cin>>a[i];
}
for(int i=n-m; i<n; i++){
cout<<a[i]<<" ";
}
for(int i=0; i<n-m-1; i++){
cout<<a[i]<<" ";
}
cout<<a[n-m-1];
return 0;
}
1009 说反话(√)
给定一句英语,要求你编写程序,将句中所有单词的顺序颠倒输出。
输入格式:
测试输入包含一个测试用例,在一行内给出总长度不超过 80 的字符串。字符串由若干单词和若干空格组成,其中单词是由英文字母(大小写有区分)组成的字符串,单词之间用 1 个空格分开,输入保证句子末尾没有多余的空格。
输出格式:
每个测试用例的输出占一行,输出倒序后的句子。
输入样例:
Hello World Here I Come
输出样例:
Come I Here World Hello
思路:
1、输入时不能用cin或者scanf,要用gets输入,但是gets在PAT编译器里不支持,使用cin.getline
空格和回车都可以作为数据之间的分格符,所以多个数据可以在一行输入,也可以分行输入。 但如果是字符型和字符串,则空格(ASCII 码为 32)无法用 cin 输入,字符串中也不能有空格,回车符也无法读入。
gets(s)函数与scanf(“%s”,s)相似,但不完全相同,使用scanf(“%s”,s) 函数输入字符串时存在一个问题,就是如果输入了空格会认为字符串结束,空格后的字符将作为下一个输入项处理,但gets()函数将接收输入的整个字符串直到遇到换行为止。
gets()函数:取到\n(我们输入的回车)于是停止读取,但是它不会把\n包含到字符串里面去。然而,和它配合使用的puts函数,却在输出字符串的时候自动换行。
2、利用二维数组存储一句话中的单个单词
char temp[100][100];
for(int i=0; i<len; i++){ //将单词分隔开存入数组temp
if(a[i]!=' '){
temp[row][col++] = a[i];
}
else{
temp[row][col] = '\0'; //表示字符串结束
row = row + 1;
col = 0;
}
}
getline(a, b):第一个参数是要存储字符串的数组的名称。第二个参数是数组的大小。当 cin.getline 语句执行时,cin 读取的字符数将比该数字少一个,为 null 终止符留出空间。
3、判断某一位是否为空格要用双引号
if(a[i]!=' ')
4、'\0’表示字符串结束
temp[row][col] = '\0'; //表示字符串结束
代码如下(20分):
#include<bits/stdc++.h>
using namespace std;
int main(){
char a[100];
cin.getline(a,100); //gets识别换行符结束输入
int len = strlen(a),row = 0,col = 0;
char temp[100][100];
for(int i=0; i<len; i++){ //将单词分隔开存入数组temp
if(a[i]!=' '){
temp[row][col++] = a[i];
}
else{
temp[row][col] = '\0'; //表示字符串结束
row = row + 1;
col = 0;
}
}
for(int i=row; i>=0; i--){
//cout<<temp[i];
printf("%s", temp[i]);
if(i>0){
//cout<<" ";
printf(" ");
}
}
return 0;
}
1010一元多项式求导
思路:
1、C中:while(scanf(“%d%d”,&d,&z) != EOF)
C++中:while(cin >> d>>z)
在黑框中手动输入时,系统并不知道什么时候到达了所谓的“文件末尾”,因此需要用 < Ctrl + Z > 组合键,然后按< Enter >键的方式来告诉系统已经到了 EOF,这样系统才会结束 while
循环输入,直到符合某种条件时结束输入。
cin>>s是有返回值的,只要s满足类型条件,就会return true,一直执行下去,而cin会忽略空格或者enter,因此,enter后不会结束循环。只能 ctrl+Z。
其实很简单:通过 get() 判断下一个输入是不是回车就行。
while(cin>>a){
...
if(cin.get()=='\n') break;
}