本次我使用的是c++,但基本上没用到c++的特性,c语言也完全可以用我的思路。
已知一个正整数能被 3 整除,要满足的条件是其各位数字之和能被 3 整除。
本题就请你判断任一给定正整数是否能被 3 整除。
输入第一行给出一个正整数 n(≤10),随后 n 行,每行给出一个正整数。题目保证每个整数都不超过 104 位。
对每个输入的整数,如果能被 3 整除,就在对应的一行中输出 Yes
,否则输出 No
。随后空 1 格,输出这个整数各位数字的和。
3
1234567890
98765432123
7257482459821364032585428796
Yes 45
No 50
No 136
这一题重点就是每一个整数的位数不超过1e4,已经超过了long long 型所能存储的最大位数,所以我们需要用string型来保存数据。
保存以后遍历数据并计算是否是3的倍数。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main() {int n,sum;scanf("%d",&n);char s[1010];for(int i=0; i<n; i++) {sum=0;scanf("%s",&s);for(int j=0; j<strlen(s); j++) {sum+=s[j]-'0';}if(sum%3==0) {printf("Yes %dn",sum);} else {printf("No %dn",sum);}}return 0;
}
#include<bits/stdc++.h>
using namespace std;
int main()
{int n,sum;cin>>n;string s;for(int i=0;i<n;i++){sum=0;cin>>s;for(int j=0;j<s.size();j++){sum+=s[j]-'0';}if(sum%3==0){cout<<"Yes "<<sum<<endl;} else {cout<<"No "<<sum<<endl;}}return 0;
}
有一道推理题的原文是这样的:甲、乙、丙、丁、戊的生日是在连续的五天里,先后顺序满足以下条件:
问另外四人的生日分别在星期几?
现在我们把条件一般化,任意打乱他们的顺序,任意给定其中一人的生日,请你编写程序推算另外四人的生日分别在星期几。
注意到在上述条件描述中,只有“戊”这个人是没有任何信息直接给出的,其他人都有一个与他人关系或自己生日的描述。
输入分 5 行,每行给出一个人的已知信息。其中:
?
,则表示这个人是原文中的“戊”,没有任何信息直接给出。-2
,则表示这个人比 ?
对应的人大 2 天。-x
,则表示这个人比那个生日已知的人大 x
天。+x
,则表示这个人比 ?
对应的人小 x
天。在一行中按照输入的顺序给出对应每个人的生日,数字间和行首尾都不要有空格。
3
?
-2
-x
+x
32714
注意:星期一的前一天是星期日。样例输出中,第三个人最大,是星期日过生日。
这一题重点就是找到甲乙丙丁戊五人之间的关系。
首先,由题意可知:
然后因为五天是连续的
所以
这就是五天的之间的关系
知道五天之间的关系以后,代码就变得十分简单了。
#include<stdio.h>
#include<string>
#include<stdlib.h>
int main() {int c[5],h;char s[5][2];for(int i=0; i<5; i++) {scanf("%s",&s[i]);//保存已知量if(s[i][0]>='1'&&s[i][0]<='7') {c[i]=s[i][0]-'0';h=c[i];}}//通过已知的数来判断其他的天数//重点就是星期一的前一天是星期日for(int i=0; i<5; i++) {if(s[i][0]>='1'&&s[i][0]<='7') {continue;}if(s[i][0]=='?') {if(h!=1)c[i]=h-1;elsec[i]=7;} else if(s[i][1]=='2') {if(h>3)c[i]=h-3;elsec[i]=h-3+7;} else if(s[i][0]=='-') {if(h>2)c[i]=h-2;elsec[i]=h-2+7;} else if(s[i][0]='+') {if(h!=7)c[i]=h+1;elsec[i]=1;}}for(int i=0; i<5; i++) {printf("%d",c[i]);}return 0;
}
#include<bits/stdc++.h>
using namespace std;
int main()
{int c[5],h;string s[5];for(int i=0;i<5;i++){cin>>s[i];//保存已知量if(s[i][0]>='1'&&s[i][0]<='7'){c[i]=s[i][0]-'0';h=c[i];}}//通过已知的数来判断其他的天数//重点就是星期一的前一天是星期日for(int i=0;i<5;i++){if(s[i][0]>='1'&&s[i][0]<='7'){continue;}if(s[i][0]=='?'){if(h!=1)c[i]=h-1;elsec[i]=7;}else if(s[i][1]=='2'){if(h>3)c[i]=h-3;elsec[i]=h-3+7;} else if(s[i][0]=='-'){if(h>2)c[i]=h-2;elsec[i]=h-2+7;} else if(s[i][0]='+'){if(h!=7)c[i]=h+1;elsec[i]=1;}}for(int i=0;i<5;i++){cout<<c[i];}return 0;
}
“计算小达人”争霸赛开始啦!因为参加比赛的小朋友太多了,老师们来不及人工判题,就请你写个程序来帮忙。你要根据每位小朋友的答题记录判断他/她答对了多少题,并且给出冠军的名字。
输入第一行给出 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!
一个最基本的模拟题
重点 考虑名字之间没有空格和 符号数字之间有空格 需要用不同的方法输入
因为告诉了我们每个数字都是两位数,所以可以直接计算。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main() {int n,m,maxn=0;char s[15],t[15],tt[15];scanf("%d %d",&n,&m);for(int i=0; i<n; i++) {int sum=0;scanf("%s",&s);getchar();//读取换行符for(int j=0; j<m; j++) {//因为含有空格 直接getsgets(t);int a,b,c;//直接计算 a b ca=10*(t[0]-'0')+(t[1]-'0');b=10*(t[5]-'0')+(t[6]-'0');c=10*(t[10]-'0')+(t[11]-'0');if(a+b==c) {sum++;}//因为只有一个冠军 所以这里用<= 防止只有一个小朋友且得分为0 这样会没有答案if(maxn<=sum) {strcpy(tt,s);maxn=sum;}}printf("%s %dn",s,sum);}printf("Guan Jun Shi %s!",tt);return 0;
}
#include<bits/stdc++.h>
using namespace std;
int main()
{int n,m,maxn=0;string s,t,tt,str="n";cin>>n>>m;for(int i=0;i<n;i++){int sum=0;cin>>s;//读取换行符getline(cin,str);for(int j=0;j<m;j++){//因为含有空格 所以直接getlinegetline(cin,t);int a,b,c;//直接计算 a b ca=10*(t[0]-'0')+(t[1]-'0');b=10*(t[5]-'0')+(t[6]-'0');c=10*(t[10]-'0')+(t[11]-'0');if(a+b==c){sum++;}//因为只有一个冠军 所以这里用<= 防止只有一个小朋友且得分为0 这样会没有答案if(maxn<=sum){tt=s;maxn=sum;}}cout<<s<<" "<<sum<<endl;}cout<<"Guan Jun Shi "<<tt<<"!";return 0;
}
一个分组数列是按以下规律定义的:第 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<stdio.h>
const int N=1e5;
//这里用2*N是为了防止数据超出
int n,sum[2*N],he,tt;
int main() {scanf("%d",&n);int t=1,j=1;he=0;//对数据进行预处理while(he<=N) {he+=1;sum[he]=j;j++;for(int i=1; i<t; i++) {he+=3;sum[he]=j;j++;}t++;}//直接查询 不再处理数据for(int i=0; i<n; i++) {scanf("%d",&tt);if(sum[tt]!=0) {printf("%dn",sum[tt]);} else {printf("Not Foundn");}}return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int N=1e5;
//这里用2*N是为了防止数据超出
int n,sum[2*N],he,tt;
int main()
{cin>>n;int t=1,j=1;he=0;//对数据进行预处理while(he<=N){he+=1;sum[he]=j;j++;for(int i=1;i<t;i++){he+=3;sum[he]=j;j++; }t++;}//直接查询 不再处理数据for(int i=0;i<n;i++){cin>>tt;if(sum[tt]!=0){cout<<sum[tt]<<endl;} else {cout<<"Not Found"<<endl;}}return 0;
}
某队列允许在其两端进行入队操作,但仅允许在一端进行出队操作。现给定入队的序列,请你判断一系列出队序列是否可能。例如按 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
因为这道题的数据很小(1-n),那么深搜(dfs)的时间复杂度(o!)也满足要求
我的想法:首先题目的进队顺序是固定的 但没有要求入队完以后再出队 可以随时出队
那我们在满足出队顺序要求的时候直接出队 不会影响后面的顺序
这样我们就进行深度搜索 将所有的情况列出来 判断是否有这种情况
通过数组来模拟队列
#include<stdio.h>
const int N=1e5;
//sum 存储的是入队顺序 t存储的是出队顺序 h存储的是出队的所有可能性
int n,k,sum[11],t[11],h[22];
bool p;
//i代表入队的位数 j代表出队的位数 r代表往左放 l代表往右放
void dfs(int i,int j,int r,int l) {//如果满足出队顺序 p为真if(j==k) {p=true;return;}//如果满足出列的部分条件 直接出列if(h[11-r+1]==t[j]) {h[11-r+1]=0;dfs(i,j+1,r-1,l);}//只有当上面还能有放的情况下才能继续放if(i<n) {//如果队列里面没有数if(r==0&&l==0) {//以11为中心h[11]=sum[i];dfs(i+1,j,r+1,l);}//如果现在下面需要的数等于上面的数 那么我们就放在左边//这样可以极大的节省时间else if(sum[i]==t[j]) {h[11-r]=sum[i];dfs(i+1,j,r+1,l);}//如果没有特殊情况//这个是放在左边h[11-r]=sum[i];dfs(i+1,j,r+1,l);//这个是放在右边h[11+l+1]=sum[i];dfs(i+1,j,r,l+1);}return;
}
int main() {scanf("%d %d",&n,&k);for(int i=0; i<n; i++) {scanf("%d",&sum[i]);}//假设左端为出口for(int i=0; i<k; i++) {for(int j=0; j<n; j++) {scanf("%d",&t[j]);}//先放再判断//数据初始化p=false;for(int k=0; k<22; k++) {h[k]=0;}dfs(0,0,0,0);if(p) {printf("yesn");} else {printf("non");}}return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int N=1e5;
//sum 存储的是入队顺序 t存储的是出队顺序 h存储的是出队的所有可能性
int n,k,sum[11],t[11],h[22];
bool p;
//i代表入队的位数 j代表出队的位数 r代表往左放 l代表往右放
void dfs(int i,int j,int r,int l){//如果满足出队顺序 p为真if(j==k){p=true;return;}//如果满足出列的部分条件 直接出列if(h[11-r+1]==t[j]){h[11-r+1]=0;dfs(i,j+1,r-1,l);}//只有当上面还能有放的情况下才能继续放if(i<n){//如果队列里面没有数if(r==0&&l==0){//以11为中心 h[11]=sum[i];dfs(i+1,j,r+1,l);}//如果现在下面需要的数等于上面的数 那么我们就放在左边//这样可以极大的节省时间else if(sum[i]==t[j]){h[11-r]=sum[i];dfs(i+1,j,r+1,l);}//如果没有特殊情况//这个是放在左边h[11-r]=sum[i];dfs(i+1,j,r+1,l);//这个是放在右边h[11+l+1]=sum[i];dfs(i+1,j,r,l+1); }return;
}
int main()
{cin>>n>>k;for(int i=0;i<n;i++){cin>>sum[i];}//假设左端为出口 for(int i=0;i<k;i++){for(int j=0;j<n;j++){cin>>t[j];}//先放再判断//数据初始化p=false;for(int k=0;k<22;k++){h[k]=0;}dfs(0,0,0,0);if(p){cout<<"yes"<<endl;} else {cout<<"no"<<endl;}}return 0;
}
总体难度不算高,但最后一题比较难。
第一题就考察大数据的存储
第二题就考察的数学思维 考虑到五人之间的天数关系
第三题就考察的模拟,模拟的难度也不算大,需要注意细节
第四题考察的是数据预处理,对于多次询问,我们该如何处理
第五题考察的是dfs/(学长说的是大模拟,可以用set来解决,但我懒得想了)
如果有什么不懂的话或者更好的想法,欢迎评论区讨论!
本文发布于:2024-01-29 10:50:38,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170649664014754.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |