文章目录
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,那最后再输入下次循环的第一个值,就直接退出了,如下图所示
正常代码的结果如下:就是没任何输入