B-1 被3整除 简单1次过
已知一个正整数能被 3 整除,要满足的条件是其各位数字之和能被 3 整除。 本题就请你判断任一给定正整数是否能被 3 整除。
输入格式: 输入第一行给出一个正整数 n(≤10),随后 n 行,每行给出一个正整数。题目保证每个整数都不超过 104 位。
输出格式: 对每个输入的整数,如果能被 3 整除,就在对应的一行中输出 Yes,否则输出 No。随后空 1 格,输出这个整数各位数字的和。
输入样例:
3
1234567890
98765432123
7257482459821364032585428796
输出样例:
- Yes 45
- No 50
- No 136
思想
字符串存储
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int solve(string x)
{
LL sum = 0;
for (int i = 0; i < x.size(); i++)
{
sum += x[i]-'0';
}
return sum;
}
int main()
{
int n; cin >> n;
for (int i = 0; i < n; i++)
{
LL sum = 0;
string x; cin >> x;
sum=solve(x);
if (sum % 3 == 0)
{
cout << "yes" << " " << sum << endl;
}
else
{
cout << "No" << " " << sum<<endl;
}
}
return 0;
}
B-2 生日推算
有一道推理题的原文是这样的:甲、乙、丙、丁、戊的生日是在连续的五天里,先后顺序满足以下条件:
- 甲比丙大几天,乙就比戊小几天;
- 丁比戊大 2 天;
- 丙的生日是在星期三。 问另外四人的生日分别在星期几?
现在我们把条件一般化,任意打乱他们的顺序,任意给定其中一人的生日,请你编写程序推算另外四人的生日分别在星期几。
注意到在上述条件描述中,只有“戊”这个人是没有任何信息直接给出的,其他人都有一个与他人关系或自己生日的描述。
输入格式:
输入分 5 行,每行给出一个人的已知信息。其中:
-
如果是一个 [1, 7] 区间内的整数,则表示这个人的生日已知。数字 1 到 7 顺次表示星期一到星期日。
-
如果是一个问号 ?,则表示这个人是原文中的“戊”,没有任何信息直接给出。
-
如果是 -2,则表示这个人比 ? 对应的人大 2 天。
-
如果是 -x,则表示这个人比那个生日已知的人大 x 天。
-
如果是 +x,则表示这个人比 ? 对应的人小 x 天。
输出格式:
在一行中按照输入的顺序给出对应每个人的生日,数字间和行首尾都不要有空格。
输入样例:
3
?
-2
-x
+x
输出样例:
32714
注意:星期一的前一天是星期日。样例输出中,第三个人最大,是星期日过生日。
code
作者:狮子王司
链接:https://www.zhihu.com/question/292174259/answer/3218071939
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
#include<bits/stdc++.h>
using namespace std;
int main()
{
vector<string> res;
int t=5;
int a;
while(t--)
{
string s;
cin>>s;
if(s[0]>='1'&&s[0]<='7') a=s[0]-'0';
res.push_back(s);
}
unordered_map<string,int>h;
if(a==1)
{
h["-2"]=5;
h["-x"]=6;
h["?"]=7;
h["1"]=1;
h["+x"]=2;
}
else if(a==2)
{
h["-2"]=6;
h["-x"]=7;
h["?"]=1;
h["2"]=2;
h["+x"]=3;
}
else if(a==3)
{
h["-2"]=7;
h["-x"]=1;
h["?"]=2;
h["3"]=3;
h["+x"]=4;
}
else if(a==4)
{
h["-2"]=1;
h["-x"]=2;
h["?"]=3;
h["4"]=4;
h["+x"]=5;
}
else if(a==5)
{
h["-2"]=2;
h["-x"]=3;
h["?"]=4;
h["5"]=5;
h["+x"]=6;
}
else if(a==6)
{
h["-2"]=3;
h["-x"]=4;
h["?"]=5;
h["6"]=6;
h["+x"]=7;
}
else
{
h["-2"]=4;
h["-x"]=5;
h["?"]=6;
h["7"]=7;
h["+x"]=1;
}
for(auto x:res) cout<<h[x];
return 0;
}
B-3 计算小达人争霸赛 简单1次过
“计算小达人”争霸赛开始啦!因为参加比赛的小朋友太多了,老师们来不及人工判题,就请你写个程序来帮忙。你要根据每位小朋友的答题记录判断他/她答对了多少题,并且给出冠军的名字。
输入格式:
输入第一行给出 2 个正整数 N(≤1000)和 M(≤100),分别为参赛小朋友的人数和每人回答的问题数。接下来给出 N 个小朋友的答题记录,格式为:
小朋友姓名
A1 + B1 = C1
A2 + B2 = C2
...
AM + BM = CM
其中小朋友姓名是不含空格、仅由英文字母组成的、不超过 20 个字符的字符串。随后的 M 行,每行给出一个加法算式,算式中的每个数字都是两位数的正整数,数字和加号、等号间都有 1 个空格分隔。
输出格式:
判断每个加法算式是否正确,从而统计出每个小朋友做对了多少题。做对最多题数的是冠军。题目保证冠军只有 1 个。输出的格式为:首先按照输入的顺序,每行输出一个小朋友的姓名和他/她做对的题目数,其间以 1 个空格分隔。最后一行输出:Guan Jun Shi XXX!,这里 XXX 就是冠军的姓名。
输入样例:
4 3
XiaoHua
12 + 34 = 46
21 + 39 = 50
45 + 28 = 12
XiaoMing
22 + 33 = 55
58 + 13 = 71
67 + 30 = 97
XiaoLiang
30 + 20 = 40
18 + 19 = 35
37 + 42 = 77
XiaoHong
25 + 36 = 61
81 + 12 = 93
17 + 48 = 55
输出样例:
XiaoHua 1
XiaoMing 3
XiaoLiang 0
XiaoHong 2
Guan Jun Shi XiaoMing!
思想
模拟题,按照要求模拟即可。我这里把加法算式用字符串读入,然后提取出来两个加数与和,判断一下加数相加的和与读入的和是否一致即可。
code
#include<bits/stdc++.h>
using namespace std;
int maxcnt = -1;
string maxname,name;
int cnt;
int main()
{
int n, m; cin >> n >> m;
for (int i = 0; i < n; i++)
{
cin >> name;
cnt=0;
getchar();
for (int j = 0; j < m; j++)
{
string qian = "", hou = "", op = "",sum="";
string s; getline(cin,s);
int k = 0;
//提取第一个加数
while(isdigit(s[k])&&k<s.size())
{
qian += s[k];
k++;
}
while (!isdigit(s[k]))k++; //跳过空格和+号
//提取第二个加数
while (isdigit(s[k])&&k<s.size())
{
hou += s[k];
cout << "s[k]:" << s[k] << endl;
k++;
}
while (!isdigit(s[k]))k++; //跳过空格和=号
//提取和
while (isdigit(s[k]) && k < s.size())
{
sum += s[k];
k++;
}
//cout << "调试: "<<qian << " " << " " << hou <<" "<<sum << endl;
int ans = stoi(qian) + stoi(hou);
//cout << "ans: sum:" << ans << " " << sum << endl;
if (ans == stoi(sum))cnt++;
}
cout << name << " " << cnt << endl;
if (cnt > maxcnt)
{
maxcnt = cnt;
maxname = name;
}
}
cout << "Guan Jun Shi " << maxname;
return 0;
}
方法2
作者:狮子王司
链接:https://www.zhihu.com/question/292174259/answer/3218071939
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
#include<bits/stdc++.h>
using namespace std;
struct student
{
string name;
int sum;
};
const int N=1010;
student e[N];
bool check(string s)
{
string s1=s.substr(0,2);
string s2=s.substr(5,2);
string s3=s.substr(10,2);
int a(0),b(0),c(0),t=10;
for(int i=0;i<s1.size();i++)
{
a+=(s1[i]-'0')*t;
b+=(s2[i]-'0')*t;
c+=(s3[i]-'0')*t;
t=1;
}
if(a+b==c) return true;
else return false;
}
bool cmp(student a,student b)
{
return a.sum>b.sum;
}
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
e[i].sum=0;
if(i==1) getchar();
getline(cin,e[i].name);
for(int j=0;j<m;j++)
{
string s;
getline(cin,s);
if(check(s)) e[i].sum++;
}
cout<<e[i].name<<" "<<e[i].sum<<endl;
}
sort(e+1,e+1+n,cmp);
cout<<"Guan Jun Shi "<<e[1].name<<"!"<<endl;
return 0;
}
B-4 分组数列
一个分组数列是按以下规律定义的:第 1 组包含 1 个数字,为 0×3+1;第 2 组包含 2 个数字,为 0×3+2 和 1×3+2;第 3 组包含 3 个数字,为 1×3+3, 2×3+3 和 3×3+3;以此类推。 一般来说,第 i 组包含 i 个数字,从上一组最后一个数字加 1 开始,每次增 3。例如第 3 组可以理解为:包含 3 个数字,从第 2 组最后一个数字 5 加 1(即 6)开始,增 3 得到第 2 个数字为 9,再增 3 得到第 3 个数字为 12。
所以根据定义,这个序列前 10 个数字就是:1, 2, 5, 6, 9, 12, 13, 16, 19, 22。它们实际上分成了 4 个组,即:{1}, {2, 5}, {6, 9, 12}, {13, 16, 19, 22}。 本题就请你找出任意一个给定数字是这个数列的第几项。
输入格式:
输入第一行首先给出一个正整数 n (≤105),是待查询的数字个数。随后 n 行,每行给出一个查询的正整数,所有数字都不超过 105。
输出格式:
对每个查询的正整数,输出其在数列中的序号(从 1 开始)。如果这个数字不在数列中,则输出 Not Found。
输入样例:
4
12
16
5941
87654
输出样例:
6
8
2023
Not Found
思想
对于这种查询问题,我们直接提前预处理一下即可。这里把1-1e5分别对于的位置算出来
这样可以极大的节省时间 重新查询会超时。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int a[2 * N], tt, he;
int main()
{
int n; cin >> n;
int j = 1,t=1;
//预处理
while (he <= N)
{
he += 1;
a[he] = j;
j++;
for (int i = 1; i < t; i++)
{
he += 3;
a[he] = j;
j++;
}
t++; //t控制当前是第几轮
}
for (int i = 0; i < n; i++)
{
cin >> tt;
if (a[tt] != 0)
{
cout << a[tt] << endl;
}
else
{
cout << "Not Found" << endl;
}
}
return 0;
}
B-5 两头进一头出
某队列允许在其两端进行入队操作,但仅允许在一端进行出队操作。现给定入队的序列,请你判断一系列出队序列是否可能。例如按 1、2、3、4、5 的顺序入队,则 1、3、2、5、4 这样的出队序列是可以得到的,但 5、1、3、2、4 就是不可能得到的。
输入格式:
输入首先在一行中给出两个正整数 N 和 K(≤10),分别是入队元素的个数和待查验的序列个数。随后一行给出 N 个两两不同的整数(每个都不超过 106)组成的入队序列;再跟着 K 行,每行给出由 N 个入队整数组成的出队序列。同行整数间以空格分隔。
输出格式:
对每个需要查验的出队序列,如果是可能的,则在一行中输出 yes,否则输出 no。
输入样例:
5 4
10 2 3 4 5
10 3 2 5 4
5 10 3 2 4
2 3 10 4 5
3 5 10 4 2
输出样例:
yes
no
yes
no
思想
模拟一下入队出队的过程,首先用给定的出队队列做一个哈希映射,映射一下出队队列元素的下标。然后去入队队列中找。
如果下一个要入队的元素和比当前入队队列队头的下标大,说明下一个要入队的元素出队要晚,那么就加入队尾,否则说明比当前入队队列队头出队早,将它加入到队头。
code
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
const int N = 1e6 + 10;
int n, k;
int a[N], b[N],idx[N];
bool check()
{
int res= 1;
deque<int>q;
for (int i = 1; i <= n; i++)
{
if (q.empty())q.push_back(a[i]);
else
{
int t = q.front();
if (idx[a[i]] > idx[t])q.push_back(a[i]); //说明a[i]要比队头后出队,加入队尾
else q.push_front(a[i]);
}
while (q.size() && q.front() == b[res]) //出队队列队头和入队队列队头一样,满足出队要求
q.pop_front(), res++;
}
return res == n + 1; //是否所有出队元素都从入队队列中出队
}
void solve()
{
cin >> n >> k;
for (int i = 1; i <= n; i++)cin >> a[i];
while (k--)
{
bool flag = 1;
for (int i = 1; i <= n; i++)
{
cin >> b[i];
idx[b[i]] = i;
if (a[i] != b[i])flag = 0;
}
if (flag)cout << "yes" << endl; //a[i]=b[i],说明入队顺序本身就是一种出队顺序
else cout << (check()?"yes":"no") << endl;
}
}
int main()
{
cin.tie(nullptr)->sync_with_stdio;
int t = 1;
while (t--)
{
solve();
}
return 0;
}