pat 乙级 1051~1060

文章目录

1051
1052
1053
1054
1055
1056
1057
1058
1059
1060


1051

解题思路1:

1.通过极坐标的形式进行复数相乘,如下图
2.对于特殊情况,比如A=-0.0001,如果直接保留2位小数,则为-0.00而非0.00,而这种情况,只针对A<0且A+0.005>0
3.对于B有三种情况,大于等于0是直接输出;与A类似的一种情况;B小于0并且B小于-0.005

在这里插入图片描述

参考代码:

#include <iostream>
#include <cmath>
using namespace std;
/*
    解题思路:

*/
int main() 
{
     double r1, p1, r2, p2, A, B;
     cin >> r1 >> p1 >> r2 >> p2;
     A = r1 * r2 * cos(p1) * cos(p2) - r1 * r2 * sin(p1) * sin(p2);
     B = r1 * r2 * cos(p1) * sin(p2) + r1 * r2 * sin(p1) * cos(p2);
     if (A + 0.005 > 0 && A < 0)
        printf("0.00");
     else
        printf("%.2f", A);
        
     if(B >= 0)
        printf("+%.2fi", B);
     else if (B + 0.005 > 0 && B < 0)
        printf("+0.00i");
     else
        printf("%.2fi", B);
     return 0; 
 }

1052

解题思路:

1.将输入样例,转化为字符数组
2.按照要求输出

参考代码:

#include <iostream>
#include <vector>
using namespace std;
/*
    解题思路:

*/
int main()
{
     //

     /*
        1.定义一个字符串的二维数组v(有3行)
        2.使用getline接受字符串
        3.设置两个循环变量j,k分别表示[和]的位置
        4.用双层while-if嵌套将表情放到row(row表示一行表情字符串)中,再将row放到v中
     */
     vector<vector<string>> v;

     for(int i=0; i<3; i++)
     {
         string s;
         getline(cin,s);
         vector<string> row;    //定义一个字符数组
         int j=0, k=0;
         while(j < s.length())
         {
             if(s[j] == '[')
             {
                 /*
                    k直接在此处自增是因为,如果第一次k走到]这个位置,if判断为真,压入栈,退出循环,其实
                    k已经走到下一个位置也就是下一个[处,如果将k放到if后面自增的话,那么k的值一直不变。
                 */
                 while(k++ < s.length())
                 {
                     if(s[k] == ']')
                     {
                         row.push_back(s.substr(j+1, k-j-1));
                         break;
                     }
                 }
             }
             j++;
         }
         v.push_back(row);
     }

     int n;
     cin >> n;
     for(int i = 0; i < n; i++)
     {
         int a, b, c, d, e;
         cin >> a >> b >> c >> d >> e;
         /*
            如果这里输入的数字,大于字符数组中字符元素的长度的话,输出Are you kidding me? @\/@,由于每个
            字符串都是从1开始,所以如果输出0,也是选择的序号不存在,就输出Are you kidding me? @\/@
         */
         if(a>v[0].size() || b>v[1].size() || c>v[2].size() || d>v[1].size() || e>v[0].size() || a<1 || b<1 || c<1 || d<1 || e<1)
         {
             cout << "Are you kidding me? @\\/@" << endl;
             continue;
         }
         cout << v[0][a-1] << "(" << v[1][b-1] << v[2][c-1] << v[1][d-1] << ")" << v[0][e-1] << endl;
     }
     return 0;
 }


知识总结:

1.用vector嵌套一个字符串数组
vector<vector<string>> v;
2.用getline接受一个字符串
getline(cin,s);
3.给字符串压栈
s.push_back(a);  //将字符串a压栈到s中
4.截取字符串
s.substr(k,j);   //表示在s字符串中,第k个位置,一共截取j个字符

1053

解题思路:

1.设置knkz,kz,

2.利用双层for比较:N,e,D,a 先比较电量是否高于观察期的一半,如果高于,则再判断是否大于指定的天数,计算
出knkz和kz的个数,最后再求百分比后输出

参考代码:

#include<iostream>
#include<cstdio>
using namespace std;
/*
    解题思路:

*/
int main()
{
    /*
        注意事项:
        1.对“可能控制”,“控制”的判断,先if判断是否存在超过一半的日子用电量低于某给定的阈值e,然后用一个
        ?:进一步判断是否观察期超过某给定阈值 D 天,然后选择是对knkz自增还是kz自增
        2.输出%时,应该输出两个%
    */
    int N,D,a;
    double e,knkz=0.0,kz=0.0;
    double temp=0.00;
    cin >> N >> e >> D;
    for(int i=0; i<N; i++)
    {
        cin >> a;
        int tempcount=0;
        for(int j=0; j<a; j++)
        {
            cin >> temp;
            if(temp<e)
                tempcount++;
        }
        if(tempcount>a/2)
        {
            a>D?kz++:knkz++;
        }
    }
    printf("%.1f%% %.1f%%",knkz/N*100,kz/N*100);
    return 0;
}

注意事项:

    1.对“可能控制”,“控制”的判断,先if判断是否存在超过一半的日子用电量低于某给定的阈值e,然后用一个
    ?:进一步判断是否观察期超过某给定阈值 D 天,然后选择是对knkz自增还是kz自增
    2.输出%时,应该输出两个%

1054

解题思路:

1.用字符数组来存放输入的值
2.不管a是啥,都将a转化为浮点型的数放到临时变量temp中
      1.对于整数,实数而言,直接将字符类型转化为双精度浮点数
      2.对于字母串而言,转化成的双精度浮点数是一个极小的数,比如aaa,转化为7.98855e-305
      3.对于有多个小数点而言,只取到第2个小数点之前
3.在将temp保留2位小数,放到字符数组中,以a的长度为基准,遍历循环如果,a[i]!=b[i]则flag=1
4.如果flag=1或者temp<-1000 或者temp>1000,则输出:ERROR: aaa is not a legal number
5.否则累加temp,并记录个数
6.如果个数为1,则直接输出sum;如果个数为0,则输出undefined,否则输出:The average of 3 numbers is 1.38

参考代码:

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int main()
{
    char a[50],b[50];
    double sum=0.0,temp=0.0;
    int n,cnt=0;
    cin >> n;
    for(int i=0; i<n; i++)
    {
        scanf("%s",a);
        sscanf(a,"%lf",&temp);
        sprintf(b,"%.2f",temp);

        int flag=0;

        for(int j=0; j<strlen(a); j++)      //对于字符数组而言,用strlen去求其长度
            if(a[j]!=b[j])
                flag=1;

        if(flag || temp<-1000 || temp>1000)
        {
            cout << "ERROR: " << a <<  " is not a legal number" << endl;
            continue;
        }

        else
        {
            sum+=temp;
            cnt++;
        }
    }
    //根据上面cnt的结果,输出对于字符串,而不是对于每个字符串都要输出平均值结果
        if(cnt==1)
            printf("The average of 1 number is %.2f\n",sum);  //对于只有一个值时,直接输出sum,并且保留2位小数
        else if(cnt>1)
            printf("The average of %d numbers is %.2f\n", cnt, sum / cnt);  //printf不能与endl结合
        else
            cout << "The average of 0 numbers is Undefined" << endl;
        return 0;

}

注意事项:

1.后面的if-else是对于输出平均值的字符串,共3中情况:
      1.只有1个值时,则直接输出sum,保留2位小数
      2.没有值时,则直接输出The average of 0 numbers is Undefined
      3.如果cnt>1则,输出sum/cnt,并保留2位小数即可

知识总结:

1.将字符数组a以浮点数的方式保存到temp中
 sscanf(a, "%lf", &temp);  //将a以浮点型的方式放到temp中
2.将temp变量以保留2位小数的方式输出到字符数组b中
char a[50], b[50];
sprintf(b, "%.2f",temp);

1055

解题思路1:

1.用结构数组来存储人名和身高
2.自定义一个cmp,如果身高不同的话,则按身高降序排列(对于输出是先输出最后一排,所以按照降序排列),身高相同按照名字的升序排列,对结构数组进行排序
3.设置两个边t,row分别表示:t表示结构数组中,按照n/k分配好的第一个下标,row表示行树,初值分别为0,k
4.如果row==k,则让m=n-n/k*(k-1)表示最后一行人数,如果row!=k,则m=n/k表示每行的人数
5.定义一个字符串数组ans,来存放人名。从按照n/k划分好的结构数组中将人名放到ans中,当然先一次性放完左边合适的人名,然后
再一次性放完右边合适的人名

6.按照输出要求输出这一排人名
7.不要忘记row–,t+=m

参考代码:

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
/*
    解题思路:

*/

//设置一个结构
struct node 
{
     string name;
     int height;
};

//设置一个cmp,用:?来表示,如果身高不同的话,则按降序排列,身高相同按照名字的升序排列
int cmp(struct node a, struct node b) 
{
    return a.height != b.height ? a.height > b.height : a.name < b.name; 
}

int main() 
{
     int n, k, m;
     cin >> n >> k;
     
     //用vector来定义一个结构数组
     vector<node> stu(n);
     
     for(int i = 0; i < n; i++) 
     {
         cin >> stu[i].name;
         cin >> stu[i].height;
     }
     
     sort(stu.begin(), stu.end(), cmp);
     
     int t = 0, row = k;
     
     while(row) 
     {
         if(row == k)   //对于最后一排而言,肯定要先输出,然后依次是n/k的个数,m表示每排的人数
         {
            m = n-n / k * (k - 1);
         } 
        else 
          {
            m = n / k;
          }
        
        //定义一个字符串数组,表示每排的人名
         vector<string> ans(m);
         
         //t初值是0,又因为结构数组,按照身高降序排列,名字升序排列,所以stu[t].name就表示身高在这排中最大的人名,ans[m/2]=stu[t].name就是把每排中身高最大的人放到中间
         //t在样例中的值分别是0,4,7,t表示结构数组中,按照n/k分配的第一个下标
         ans[m / 2] = stu[t].name;
         
         // 左边⼀列
         /*
            1.j是人名字符串数组ans的变量,i是结构数组stu的变量
            2.j=m/2-1,表示从紧靠中间的左边开始
            3.对于for含义是一次直接将左边合适的人名全部输出,所以变量i是递增2
                1.i=t+1; 表示从按照划分的结构数组中的第2个位置开始,都放在左边
    
         */
         int j = m / 2 - 1;
         for(int i = t + 1; i < t + m; i = i + 2)
            ans[j--] = stu[i].name;
            
         // 右边⼀列
         /*
            1.j=m/2+1; 表示从紧靠中间的右边开始
            2.i从t+2开始,表示从按照划分的结构数组中的第3个位置开始,都放在右边
         */
         j = m / 2 + 1;
         for(int i = t + 2; i < t + m; i = i + 2)
            ans[j++] = stu[i].name;
            
         // 输出当前排
         cout << ans[0];
         for(int i = 1; i < m; i++)
            cout << " " << ans[i];
         cout << endl;
         t = t + m;
         row--;
     }
     return 0; 
 }

知识总结:

1.自定义cmp,对结构数组进行排序
struct node
{
    string name;
    int tall;
};

int cmp(node a,node b)  //是对结构进行排序,所以必须定义两个结构node类型的变量a,b。函数类型还是int。如果身高不同按照降序排列,否则按照名字的升序排列
{
    return a.tall!=b.tall?a.tall>b.tall:a.name<b.name;
}
int main()
{
    int m,n,k;
    cin >> n >> k;
    vector<node> stu(n);
    for(int i=0; i<n; i++)
        cin >> stu[i].name >> stu[i].tall;
    sort(stu.begin(),stu.end(),cmp);
    
}


1056

解题思路:

1.通过观察,可知sum+=a[i] * 11 * (n-1)

参考代码:

#include<iostream>
using namespace std;
int main(){
    int n,sum=0;
    cin >> n;
    int a[n];
    for(int i=0; i<n; i++){
        cin >> a[i];     
        sum+=a[i]*11*(n-1);           
    }
    cout << sum;
    return 0;
}



1057

解题思路1:

1.先计算字符串中字母的所代表值的和
2.对其进行2进制计算,同时计算1,0的个数

参考代码1:

#include<iostream>
using namespace std;
/*
    解题思路:

*/
int main()
{
    string s;
    getline(cin,s);
    int sum=0,temp,ycount=0,lcount=0;
    for(int i=0; i<s.size(); i++)
    {

        if('a'<=s[i] && s[i]<='z')
            temp=s[i]-'a'+1;
        else if('A'<=s[i] && s[i]<='Z')
            temp=s[i]-'A'+1;
        else
            continue;
        sum+=temp;
    }
    while(sum!=0)
    {
        if(sum%2)
            ycount++;
        else
            lcount++;
        sum/=2;
    }
    cout << lcount << " " << ycount;

    return 0;
}

解题思路2:

1.用getline输入一个字符串
2.通过for循环,首先用isalpha判断是否为字母,若是,用toupper将字母改为大写字母,然后累加
3.统计n为2进制时,0和1的个数

参考代码2:

#include<iostream>
#include<string>
using namespace std;
int main()
{
    string s;
    getline(cin,s);
    int n=0;
    for(int i=0; i<s.length(); i++)
        if(isalpha(s[i]))
        {
            s[i]=toupper(s[i]);
            n+=(s[i]-'A'+1);
        }
    int cnt0=0,cnt1=0;
    while(n!=0)
    {
        if(n%2==0)
            cnt0++;
        else
            cnt1++;
        n/=2;
    }
    cout << cnt0 << " " << cnt1;
    return 0;
}

知识总结:

1.isalpha()判断ch是否为英文字母,若是英文字母返回非0(小写字母为2,大写字母为1)
2.toupper()函数是将小写字母转化为大写字母

1058

解题思路:

1.vector<set> right(m)表示标准答案的二维数组,vector total(m), wrongCnt(m);
分别表示每道题的满分情况,每道题错误次数

2.第一个双层for:输入题目的情况
      1.外层for控制m个题的循环
      2.内存for根据输入标准答案选项的个数,输入到二维数组right中
3.第二个三层for:输入学生的答题情况,以及输出每个学生的成绩
      1.外层for控制n个人
      2.内存for控制每个人答m个题的情况
      3.最内层for根据(后的数字,往set类型的st中insert学生的具体答案
4.第3个for找出错得最多的题目的错误次数
5.if-else:
      如果错误次数为0,输出too simple
      否则循环遍历题目,如果本题的错误次数与max一致,则输出i+1表示题号

参考代码:

#include <cstdio>
#include <vector>
#include <set>
#include <iostream>
using namespace std;
/*
    解题思路:

            
    注意事项:
    1.每道题的选项个数就是一个形同虚设的值,直接用temp保存,没有实际用处
    2.特别注意第二个三层for中,scanf("\n")的使用
                                 
                                 
    知识总结:
    1.set类型的变量,只能用inset输入

            
        
*/
int main()
{
     int n, m, temp, k;
     cin >> n >> m;
     vector<set<char>> right(m);   //用二维数组存放正确选项
     vector<int> total(m), wrongCnt(m);  //用int数组存放满分

     //输入题目的信息
     for(int i = 0; i < m; i++)
     {
         cin >> total[i] >> temp >> k;   //total表示满分,temp表示题目个数,k表示是正确选项个数

         //输入正确选项
         for(int j = 0; j < k; j++)
         {
             char c;
             cin >> c;
             right[i].insert(c);   //想要往set中插入值,必须使用insert
         }
     }

    //输入学生的答题情况
    /*

        2.为啥没(的输入?
           仔细看41行中有没(
    */
     for(int i = 0; i < n; i++)
     {
         int score = 0;
         scanf("\n");    //为了避免下一次的scanf直接读取\n而结束,保证每次都等待键盘输入……,也可以写成getchar()
         for(int j = 0; j < m; j++)     //这里是输入每一行中答题内容
         {
             if(j != 0)
                scanf(" ");    //用法和scanf("\n"); 一个意思
             scanf("(%d", &k);   //输入每个括号内有多少个答案
             set<char> st;
             char c;

             for(int l = 0; l < k; l++)   //将每个括号中的答案放到set中
             {
                 scanf(" %c", &c);
                 st.insert(c);
             }

             scanf(")");   //接受一个反括号

             if(st == right[j])    //如果括号中的答案和题目信息中的答案匹配,则该题为满分
             {
                score += total[j];
             }
            else
             {
                wrongCnt[j]++;   //如果答案不对,则记录该题错误的个数  记录每道题的错误个数
             }
         }
         printf("%d\n", score);
     }


     int maxWrongCnt = 0;       //设置一个最大变量
     
     for(int i = 0; i < m; i++)        //找出错得最多的题目的错误次数
     {
         if(wrongCnt[i] > maxWrongCnt)
         {
            maxWrongCnt = wrongCnt[i];
         }
     }

     if(maxWrongCnt == 0            //如果错得最多的题目的错误次数为0,输出Too simple
        printf("Too simple"); 
     else                               //首先输出错得最多的题目的错误次数,如果本题的错误次数和maxWrongCnt一致,则输出i+1
     {
         printf("%d", maxWrongCnt);
         
         for(int i = 0; i < m; i++)
         {
             if(wrongCnt[i] == maxWrongCnt)
             {
                printf(" %d", i + 1);
             }
         }
     }
     return 0;
 }

知识总结:

1.关于scanf("\n")与scanf(" ")的讨论
#include <cstdio>
#include <iostream>
using namespace std;
int main()
{
     int n,k=3;
     cin >> n;
     /*
         此代码的含义是:
         1.输入一个n,然后循环输入(k1 (k2 (k3 .... 并输出k1 k2 k3
     */
     for(int i = 0; i < n; i++)
     {
        scanf("\n");    //吃掉上面那个输入n时的回车,加入此行代码,只针对于输入带有符号的输入
        scanf("(%d", &k);  
        cout << k << endl;

     }
     return 0;
}

在这里插入图片描述

2.关于set类型的用法:
#include<iostream>
#include<set>
using namespace std;
int main()
{
    set<int> s;
    set<int>::iterator its;   //设置一个迭代器
    int temp,n;
    cin >> n;
    
     
    for(int i=0; i<n; i++)   //只能以insert的方式插入数字
    {
        cin >> temp;
        s.insert(temp);
    }
    
    
    for(its=s.begin(); its!=s.end(); its++)   //使用迭代的方式读取数字
        cout << *its;


    return 0;
}

注意事项:

1.每道题的选项个数就是一个形同虚设的值,直接用temp保存,没有实际用处
2.特别注意第二个三层for中,scanf("\n")的使用

3.如果不加循环中scanf("\n")运行结果:

在这里插入图片描述

原因是:

在输入完n后,会敲一个回车,这个回车\n进入缓冲区,而scanf遇到(空格,制表符,回车)会自动结束,所以不理下面的scanf("(%d",&k),空白区中一直有\n,所以每次循环scanf一遇到\n就结束,则一直输出3。若加上scanf("\n"),则回车时将\n吃掉,所以重新正常输入,然后输出,在进入下一次循环时,scanf("\n")还是会吃掉上一次输入完后的\n

在这里插入图片描述

如果这样写,当max为0时,则输出完Too simple 后还要输出00000
所以一定要将for写入else中


1059

解题思路1:

1.设置一个数组ran,以学号为数组下标,以排名为数组元素

2.先输出学号,用printf,用%04d,占4位输出,不足为数左端补0

3.如果ran[id]==0表示id根不不在排名里,输出Are you kidding?
4.设置set类型的集合ss,ss保存的是id号,先在ss中寻找id是否存在,是,就输出checked 不是,就把数字插进去
5.如果ran[id]==1,输出Mystery Award
6.然后排名是素数,输出Minion
7.其余输出Chocolate

参考代码:

#include<iostream>
#include<set>
using namespace std;

bool sushu(int a)
{
    if(a<=1)
        return false;
    for(int i=2; i<a; i++)
        if(a%i==0)
            return 0;
    return 1;
}

int main()
{
    int n;
    cin >> n;
    int ran[10000],id;
    for(int i=0; i<n; i++)
    {
        cin >> id;
        ran[id]=i+1;
    }

    int m;
    cin >> m;
    set<int> ss;
    for(int i=0; i<m; i++)
    {
        cin >> id;
        printf("%04d: ",id);
        if(ran[id]==0)
        {
            cout << "Are you kidding?" << endl;
            continue;
        }

        if(ss.find(id)==ss.end())
            ss.insert(id);
        else
        {
            cout << "Checked" << endl;
            continue;
        }


        if(ran[id]==1)
            cout << "Mystery Award" << endl;
        else if(sushu(ran[id]))
            cout << "Minion" << endl;
        else
            cout << "Chocolate" << endl;

    }
    return 0;
}


知识总结:

1.set中的find
if( ss.find(id) == ss.end() )  //表示ss中没有找到id这个值

1060

解题思路:

1.一般的思路肯定是,从骑行的最大公里开始,看是否有E天超过E公里,从大到小开始寻找

2.此题的思路是以E天为准,从1开始,将每天的骑行距离按照降序排列,从下标为1开始

3.a[p]>p:当p=1时,表示肯定有1天超过1公里;当p=2时,表示肯定有2天超过2公里;当p=3时,表示肯定有3天
超过3公里…一直循环到a[p]<=p此时就表示,当天的距离没有超过p,则E就是上一个值,也就是为啥ans表示E从0
开始,p从1开始,结果E就是ans

参考代码:

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;

bool cmp(int a,int b)
{
    return a>b;
}

int main()
{
    int n;
    cin >> n;
    int a[n+1];
    for(int i=1; i<=n; i++)
        cin >> a[i];
    sort(a+1,a+n+1,cmp);

    int ans=0,p=1;
    while(ans<=n && a[p]>p)
    {
        ans++;
        p++;
    }
    cout << ans;
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值