pat 乙级 1071~1080

文章目录

1071
1072
1073
1074
1075
1076
1077
1078
1079
1080


1071

解题思路:

ans表示n1和n2真实的结果,如果n1 > n2,ans为0,表示应该赌⼩,否则ans = 1,表示玩家应
该赌⼤。T表示当前玩家有的筹码数,如果T=0,表示玩家已经输光,输出Game Over;如果t > T,表
示玩家下注超过持有的筹码量,输出Not enough tokens. Total = 当前的T,如果真实结果ans等于玩家猜
的结果,表示玩家赢了,筹码都归玩家,T += t;如果ans不等于b,表示玩家输了,筹码要减去t~

参考代码:

#include <iostream>
using namespace std;
int main() {
 int T, K, n1, n2, b, t;
 scanf("%d %d", &T, &K);
 for (int i = 0; i < K; i++) {
 scanf("%d %d %d %d", &n1, &b, &t, &n2);
 int ans = n1 > n2 ? 0 : 1;
 if (T == 0) {
 printf("Game Over.\n");
return 0;
 } else if (t > T) {
 printf("Not enough tokens. Total = %d.\n", T);
 } else if (ans == b) {
 T += t;
 printf("Win %d! Total = %d.\n", t, T);
 } else if (ans != b) {
 T -= t;
 printf("Lose %d. Total = %d.\n", t, T);
 }
 }
 return 0; }

1072

解题思路1:

1.用map来存储,名字作为关键字,后面跟着一个数组
2.输出一个值,就在set中找,找到就按格式输出,并统计人数和物品数

参考代码1:

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

*/
int main()
{
    int n,m,count=0,count1=0;
    cin >> n >> m;
    set<int> s;
    map<string,vector<int>> a;
    for(int i=0; i<m; i++)
    {
        int temp;
        cin >> temp;
        s.insert(temp);
    }
    for(int i=0; i<n; i++)
    {
        string t;
        int p;
        cin >> t >> p;
        int flag=1,flag1=1;
        for(int j=0; j<p; j++)
        {
            int o;
            cin >> o;
            if(s.find(o)!=s.end())
            {
                if(flag==1)
                { 
                    cout << t << ": ";
                    count1++;
                }

                if(flag1==0)
                    cout << " ";
                printf("%04d", o);
                flag1=0;
                flag=0;
                count++;
            }
        }
        if(flag==0)
            cout << endl;
    }
    cout << count1 << " " << count;
}


解题思路2:

1.设置一个bool类型数组,以违禁品的编号为下标,数组元素为true
2.根据学生的物品对应于bool类型数组,按格式输出

参考代码2:

#include<iostream>
using namespace std;
bool kk[10000];
int main()
{
    int n,m,temp,a=0,b=0;
    cin >> n >> m;
    for(int i=0; i<m; i++)
    {
        cin >> temp;
        kk[temp]=true;
    }

    for(int i=0; i<n; i++)
    {
        string name;
        int k,flag=1;
        cin >> name >> k;
        for(int j=0; j<k; j++)
        {
            cin >> temp;
            if(kk[temp])
            {
                if(flag==1)
                    cout << name << ":";
                printf(" %04d",temp);
                a++;
                flag=0;
            }
        }
        if(flag==0)
        {
           cout << endl;
           b++;
        }
    }
    cout << b << " " << a;
}


1073

解题思路1:

一.第一个双层for循环
      1.对于每道题的满分情况放到数组fullscore中,对于每道题选项个数放到optnum中,对于每道题正确选项个数放到
truenum中
      2.根据truenum循环将每个学生每道题的按照hash的方式得到的分数放到trueopt数组中
二.第二个多层for循环:根据学生的答题情况,得出对应的分数,并输出;同时记录错的多的选项
三.找出cnt数组中的最大值maxcnt,表示错题数最大值
四.如果maxcnt为0输出too simple,否则双层for循环,找到与错题最大值相符的题目,同时输出错选的选项

参考代码:

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


*/
int main()
{
     int n, m, optnum, truenum, temp, maxcnt = 0;
     int hash[] = {1, 2, 4, 8, 16}, opt[1010][110] = {0};   //opt数组表示每行是学生答题的分数情况
     char c;
     cin >> n >> m;
     vector<int> fullscore(m), trueopt(m);    //fullscore表示每道题满分的情况
     vector<vector<int>> cnt(m, vector<int>(5));  //表示一个二维数组,m行,每行表示一个长度为5的数组
                //cnt表示错误次数

      //输入前面一部分
     for (int i = 0; i < m; i++)
     {
         cin >> fullscore[i] >> optnum >> truenum;  //fullscore[i]表示满分数组
         for (int j = 0; j < truenum; j++)
         {
             scanf(" %c", &c);
             trueopt[i] += hash[c-'a'];   //trueopt[]数组统计一道题得满分时的分数
         }
     }

     for (int i = 0; i < n; i++)
     {
         double grade = 0;
         for (int j = 0; j < m; j++)
         {
             getchar();   //接受学生每道题答案之间的那个空格
             scanf("(%d", &temp);

             for (int k = 0; k < temp; k++)
             {
                 scanf(" %c)", &c);            //先把学生的答案输入进去
                 opt[i][j] += hash[c-'a'];   //计算opt对应的值
             }

             /*
                1.通过异或运算找出全对和 选错或者漏选
                2.用过按位或找出漏选
                3.记录错误的个数(通过按位与)
             */
             int el = opt[i][j] ^ trueopt[j];    //^ 不同是非0,相同为0  el就是判断答案是否相同

             if (el)        //表示el不为0,就数值不同,一种半对半错,一种是全错
             {
                 if ((opt[i][j] | trueopt[j]) == trueopt[j])  //与0计算结果是原值,与1计算结果是1
                 { //这种情况计算的是半对半错
                    grade += fullscore[j] * 1.0 / 2;
                 }

                 if (el)   //这种情况计算的是全错,el是非0,此时要记录错误的选项
                 {
                     for (int k = 0; k < 5; k++)   //一共最多有5个答案,分别是abcde
                        if (el & hash[k])         //与0计算结果为0,与1运算结果为原值,按位与,只有对应的两个二进位都为1时,结果位才为1,参与运算的两个数均以补码出现
                            cnt[j][k]++;
                 }
             }
             else     //表示el为0,就数值相同就grade直接加
             {
                grade += fullscore[j];
             }
         }
         printf("%.1f\n", grade);
     }

     //找出错的最多的题目的错误个数
     for (int i = 0; i < m; i++)
        for (int j = 0; j < 5; j++)
            maxcnt = maxcnt > cnt[i][j] ? maxcnt : cnt[i][j];

    //如果这个maxcnt为0,表示没有题目让学生答错
     if (maxcnt == 0)
     {
        printf("Too simple\n");
     }
     else
     {
         for (int i = 0; i < m; i++)
         {
             for (int j = 0; j < 5; j++)
             {
                 if (maxcnt == cnt[i][j])       //
                    printf("%d %d-%c\n", maxcnt, i+1, 'a'+j);
             }
         }
     }
     return 0;
 }


知识总结:

1.对于本题中判断学生的答案与标答是否一致用:
/*
	用异或语句,如果答案与标答一致则el为0,否则el为非0
*/
int el = opt[i][j] ^ trueopt[j];
2.对于本题中判断学生的答案是否为半对半错用:
/*
	用按位与计算,如果是半对半错则下面执行if下的语句,否则不执行
*/
if ((opt[i][j] | trueopt[j]) == trueopt[j])
3.对于本题中判断学生的答案是否全错用:
if (el)

如果答案为全错,还要记录错误答案是哪个用:

                     for (int k = 0; k < 5; k++)   //一共最多有5个答案,分别是abcde
                        if (el & hash[k])         //与0计算结果为0,与1运算结果为原值,按位与,只有对应的两个二进位都为1时,结果位才为1,参与运算的两个数均以补码出现
                            cnt[j][k]++;

其中cnt结果如下图
在这里插入图片描述
根据循环得到cnt的过程如下:
在这里插入图片描述

对于上图中的解释如下:

第一题:对于CNT的理解。是这么理解的。对于你看,对于第一题正确答案是ac,根据三个学生的答案。第三名学生,他的答案是个BD。正确答案是ac,意思就是说。打错了,是BD,你没答是ac。这是第一题

第二题:对于第二题。正确答案是B。第一个学生答错d e。第二个学生,答案正确,第三个学生。打错e

第三题:对于第三题,正确答案是BC。第一个学生答,错是a,没达世币。第二个学生,第二个学生。他。打错了,是a,没达是C。对于第三个学生。打错是B

第四题:对于第四题,正确答案是abde第一个学生。没打底。第二个答案正确,第三个学生。答错,是c没答是e

4.opt数组结果如下:

在这里插入图片描述

5.对于trueopt数组如下:

在这里插入图片描述

6.对于hash数组如下:

在这里插入图片描述

7.scanf在for中的一些输入
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
int main()
{

int temp;
char c;
             scanf("(%d", &temp);
             for (int k = 0; k < temp; k++)
             {
                 scanf(" %c)", &c);
                cout << c << " ";
             }

     return 0;
 }

在这里插入图片描述
在这里插入图片描述


1074

解题思路:

1.将两个要相加的pat数,左边补充其位置使其和第一个字符串长度一致
2.for循环,从最后一位开始,先判断如果是10进制,则mod为10;否则就为对应的值
3.求余数,将其放到ans的最后一位;求其进位的数carry
4.如果进位的数carry不为0,一律设置为1,在最左边补为1
5.for循环输出,如果全为0,和第一个位置值为0,则都不输出

参考代码:

#include<iostream>
using namespace std;
/*
    知识总结:
    1.设置为指定长度,指定值的字符串(长度为s-s1的长度,初值全设置为0)
        string ss1(s.length()-s1.length(),'0');
*/
int main()
{
    string s,s1,s2,ans;
    int carry=0,flag=0;
    cin >> s >> s1 >> s2;
    string ss1(s.length()-s1.length(),'0');
    s1=ss1+s1;
    string ss2(s.length()-s2.length(),'0');
    s2=ss2+s2;
    ans=s;

    for(int i=s.length()-1; i>=0; i--)
    {
        int mod=s[i]=='0'?10:(s[i]-'0');
        ans[i]=(s1[i]-'0'+s2[i]-'0'+carry)%mod+'0';
        carry=(s1[i]-'0'+s2[i]-'0'+carry)/mod;
    }
    if(carry!=0)
        ans='1'+ans;
    for(int i=0; i<ans.length(); i++)
    {
        if(ans[i]!='0' || flag==1)
        {
            flag=1;
            cout << ans[i];
        }
    }
    if(flag==0)
        cout << 0;
    return 0;
}

知识总结:

1.设置为指定长度,指定值的字符串(长度为s-s1的长度,初值全设置为0)
        string ss1(s.length()-s1.length(),'0');

1075

解题思路1:

1.设置一个结构数组里面存放data和下标,设置3个vector线性表的数组
2.用地址作为下标,输入data,在输入next
3.从start开始,一直循环,根据data将<0和<=k和其他数字,分别将其地址放到v[0],v[1],v[2]
4.最后按照vector输出,也是双层for循环,按要求输出v[i][j],list[v[i][j]]…

参考代码:

#include <iostream>
#include <vector>
/*
    解题思路:

*/

using namespace std;
struct node 
{
    int data, next; 
}list[100000];

vector<int> v[3];  //3个vector线性表

int main() 
{
        int start, n, k, a;
     cin >> start >> n >> k;
     for (int i = 0; i < n; i++) 
     {
         cin >> a;
         cin >> list[a].data >> list[a].next;
     }
     
     int p = start;
     
     while(p != -1) 
     {
         int data = list[p].data;
         if (data < 0)
            v[0].push_back(p);        //v[0]全部存放<0
         else if 
            (data >= 0 && data <= k)
         v[1].push_back(p);         //v[1]全部存放<=k
         else
            v[2].push_back(p);
         p = list[p].next;
     }
     
     int flag = 0;
     for (int i = 0; i < 3; i++) 
     {
         for (int j = 0; j < v[i].size(); j++) 
         {
             if (flag == 0) 
             { //设置flag的作用是因为在排列后最后一个位置下标为-1,所以整个输出时先设置flag输出下标,空格,data,空格
                 printf("%05d %d ", v[i][j], list[v[i][j]].data);
                 flag = 1;
             } 
             else 
             {
                printf("%05d\n%05d %d ", v[i][j], v[i][j], list[v[i][j]].data);
             }
         }
     }
     printf("-1");  //最后再输出-1
     return 0; 
 }
知识总结:
1.设置一个3个线性表的vector数组:
vector<int> v[3];
2.设置结构数组:
struct stu
{
    int data,next;
}list[100001];

1076

参考代码1:

#include<iostream>
using namespace std;
/*
    解题思路:
    
*/
int main()
{
    int n;
    cin >> n;
    int a[]={1,2,3,4};
    string temp,num;
    for(int i=0; i<n; i++)
        for(int j=0; j<4; j++)
        {
            cin >> temp;
            if(temp[2]=='T')
                 num+=a[temp[0]-'A']+'0';
        }
    cout << num;
    return 0;
}

参考代码2:

#include<iostream>
using namespace std;
int main()
{
    string s;
    while(cin >> s)
    {
        if(s.size()==3 && s[2]=='T')
            cout << s[0]-'A'+1;
    }
    return 0;
}

1077

解题思路:

1.输入n,m
2.双层for循环,外层输入老师给的成绩g2,内存for循环:1.找出最大,最小值,2.并且统计所有符合条件的值,3.统计
满足条件的人数

3.按照格式输出对应的成绩

参考代码:

#include <iostream>
using namespace std;
/*

*/
int main()
{
     int n, m;
     cin >> n >> m;
     for (int i = 0; i < n; i++) 
     {
         int g2, g1 = 0, cnt = -2, temp, maxn = -1, minn = m + 1;
         cin >> g2;
         for (int j = 0; j < n-1; j++) 
         {
             cin >> temp;
             if (temp >= 0 && temp <= m) 
             {
                 if (temp > maxn) 
                    maxn = temp;
                 if (temp < minn) 
                    minn = temp;
                 g1 += temp;
                 cnt++;
             }
         }
         cout << int((((g1 - minn - maxn) * 1.0 / cnt) + g2) / 2 + 0.5) << endl;
     }
     return 0; 
 }

注意事项:

cnt的值一定要设置为cnt-2因为在cnt++中包括了最大,最小值


1078

解题思路:

1.使用if-else语句,分别构建压缩和解压的代码
2.对于解压:
      1.for循环嵌套if-else 1.for循环是根据字符串的长度
      2.if-else是根据判断s[i]是否在’1’~'9’之内
      3.是的话,就num+=s[i]
      4.不是的话,就根据num的长度将其转化为数字,循环输出对应的字符
      5.切记将cnt改为1(保证出现单个字符串时能够输出),同时将num改为""
      6.为什么要用string类型的num,因为输入的字符串是string类型的,所以可以方便的接受
      7.为什么要加 if (num.length() > 0)这个判断,因为当num的长度为0,是无法转化成数字,程序界面提示
会超出范围,这也就是为啥后面设置cnt为1以便能够让单个字符也能输出
3.对于压缩
      1.对于每一小串相同字符的字符串,每次取出第一个字符,然后统计其个数,再循环输出
      2.切记,当for按照字符串的长度循环结束时,最后还要输出剩余字符串

参考代码:

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

*/
int main()
{
     char t;
     cin >> t;
     getchar();        //接受上面的回车
     string s, num;
     getline(cin, s);
     int cnt = 1;
     if (t == 'D') //解压
     {
         for (int i = 0; i < s.length(); i++)
         {
             if (s[i] >= '0' && s[i] <= '9')
             {
                num += s[i];
             }
             else
             {
                 if (num.length() > 0)
                    cnt = stoi(num);     //将字符串转化为数字
                 while(cnt--)
                    cout << s[i];
                 cnt = 1;               //cnt设置为1,是因为要保证必须有一个字符输出
                 num = "";
             }
         }
     }
     else            //压缩
     {
         char pre = s[0];
         for (int i = 1; i < s.length(); i++)
         {
             if (s[i] == pre)
             {
                cnt++;
             }
             else
             {
                 if (cnt >= 2)
                    cout << cnt;
                 cout << pre;
                 cnt = 1;
                 pre = s[i];         //s[i]此时表示第1个值
             }
         }
         if (cnt >= 2)           //当整个字符串结束后,输出剩余的值
            cout << cnt;
         cout << pre;
     }
     return 0;
 }


    return 0;
}

知识总结:

1.将字符串转化为数字
string s="9";
int a=stoi(s);
cout << a; //此时a的值即为9

1079

解题思路1:

1.用while循环,当出现回文数时或者执行步骤>=10,就退出循环

2.输出字符串和其扭转的字符串,再输出两个字符串相加的值

3.再将两个数字相加的值转化为字符串
4.统计每次计算的步骤

参考代码:

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

*/
bool panduan(string s)
{
    for(int i=0; i<s.length(); i++)
        if(s[i]!=s[s.length()-i-1])
            return 0;
    return 1;
}
string fuhui(int a)
{
    string s;
    stringstream ss;
    ss << a;
    ss >> s;
    return s;
}
int main()
{
    string s,s1="12",s2;
    int num=0;
    cin >> s;
    if(panduan(s))       //如果输入的字符串本身就是回文,就直接输出,不要相加
    {
        cout << s << " is a palindromic number.";
        return 0;
    }

    while(!panduan(s1) && num<10)
    {
        s2=s;
        reverse(s.begin(),s.end());
        cout << s2 << " + " << s << " = " << stoi(s2)+stoi(s) << endl;
        s1=fuhui(stoi(s2)+stoi(s));
        s=s1;
        num++;
    }
    if(num==10)
        cout << "Not found in 10 iterations.";
    else
        cout << s1 << " is a palindromic number.";

}

知识总结:

1.将数字转化为字符串
#include<iostream>
#include<string>
#include<sstream>
using namespace std;
int main()
{
    int a=3333;
    string s;
    stringstream ss;
    ss << a;
    ss >> s;
    cout << s;


}

2.扭转一个字符串
//扭转一个STL字符串
#include <string>
#include <iostream>
#include <algorithm>
	using namespace std;
int main()
{


	string strSample;
	cin >> strSample;
	cout << strSample << endl << endl;

	reverse(strSample.begin(), strSample.end());
	cout << strSample;

	return 0;
}

解题思路2:

1.将字符串扭转的函数rev,模拟手动相加字符串的函数add
2.首先判断输入的字符串是否为回文是就输出,否则不管
3.while,循环条件是n–,n=10
      1.对于字符串和其自身的扭转先相加
      2.按照题意输出
      3.if判断,如果是回文就输出,并且结束程序
      4.当循环结束时,只能输出Not found in 10 iterations.

4.add函数
      1.s1表示原始字符串,s2表示其扭转的字符串
      2.设置一个变量carry表示进的那一位
      3.根据原始字符串长度,从最后一个位置开始模拟相加

参考代码2:

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

    
*/
string rev(string s)     //rev表示将字符串扭转
{
     reverse(s.begin(), s.end());
     return s;
}
string add(string s1, string s2)  //手动模拟字符串的相加
{
     string s = s1;
     int carry = 0;         //carry表示进的那一位
     for (int i = s1.size() - 1; i >= 0; i--)
     {
         s[i] = (s1[i] - '0' + s2[i] - '0' + carry) % 10 + '0';
         carry = (s1[i] - '0' + s2[i] - '0' + carry) / 10;
     }
     if (carry > 0)   //一定是先给s1前加1,在返回,否则直接return "1"+s就报错
        s = "1" + s;
     return s;
 }
int main()
{
     string s, sum;
     int n = 10;
     cin >> s;
     if (s == rev(s))
     {
                cout << s << " is a palindromic number.\n";
         return 0;
     }
     while (n--)
     {
         sum = add(s, rev(s));    //计算字符串和其扭转的字符串相加
         cout << s << " + " << rev(s) << " = " << sum << endl;
         if (sum == rev(sum))
         {
             cout << sum << " is a palindromic number.\n";
             return 0;
         }
         s = sum;
     }
     cout << "Not found in 10 iterations.\n";
     return 0;
 }

1080

解题思路:

1.设置结构node,其中结构成员包括人名,鸡屎成绩,其中成绩,期末成绩,总成绩
2.用vector设置结构数组,这样可以设置cmp,来按照总成绩降序排列,人名升序排列
3.设置一个map类型变量idx,他的作用从参加其中,期末考试的人中找到参加鸡屎的人
4.如果最终成绩>=60,就将其放到结构数组ans中
5.对ans进行cmp排列,最后输出即可

参考代码:

#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
/*
    解题思路:

*/
using namespace std;
struct node           //定义一个结构,
{
 string name;
 int gp, gm, gf, g;
};

bool cmp(node a, node b)  //设置一个按照最终成绩的递减排列,按照名字的递增排列
{
 return a.g != b.g ? a.g > b.g : a.name < b.name;
}

map<string, int> idx;

int main()
{
     int p, m, n, score, cnt = 1;
     cin >> p >> m >> n;
     vector<node> v, ans;   //设置一个结构数组
     string s;
     for (int i = 0; i < p; i++)
     {
         cin >> s >> score;
         if (score >= 200)   //当成绩>200时,直接将node结构放到数组中,并且对成绩大于200的这些人从1开始编号
         {
             v.push_back(node{s, score, -1, -1, 0});
             idx[s] = cnt++;
         }
     }
     for (int i = 0; i < m; i++)
     {
         cin >> s >> score;
         if (idx[s] != 0)     //要找出即参加机示的人且参加其中考试的人
            v[idx[s] - 1].gm = score;   //将期中成绩对应的放到结构中
     }
     for (int i = 0; i < n; i++)
     {
         cin >> s >> score;
         if (idx[s] != 0)               //要找出即参加机示的人且参加期末考试的人
         {
             int temp = idx[s] - 1;
             v[temp].gf = v[temp].g = score;  //先把所有的期末成绩gf和最终成绩g都先设置为期末考试成绩
             if (v[temp].gm > v[temp].gf)   //如果其中考试成绩gm>gf则按要求计算g
                v[temp].g = int(v[temp].gm * 0.4 + v[temp].gf * 0.6 + 0.5);
         }
     }

     for (int i = 0; i < v.size(); i++)
        if (v[i].g >= 60)
            ans.push_back(v[i]);
     sort(ans.begin(), ans.end(), cmp);
     for (int i = 0; i < ans.size(); i++)
        printf("%s %d %d %d %d\n", ans[i].name.c_str(), ans[i].gp, ans[i].gm,ans[i].gf, ans[i].g);
     return 0;
 }

注意事项:

1.如果将cnt设为0,后面代码中:
if(idx[s]!=0) 改为 if(idx[s]>=0)
v[idx[s]-1].gm=score; 改为 v[idx[s]].gm=score;
int temp=idx[s]-1; 改为 int temp=idx[s];
但是如果在第一次for循环输入时,鸡屎没有>=200,那最后再输入下次循环的第一个值,就直接退出了,如下图所示

在这里插入图片描述

正常代码的结果如下:就是没任何输入

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值