试题A:门牌制作
小蓝要为一条街的住户制作门牌号。
这条街一共有2020 位住户,门牌号从1 到2020 编号。
小蓝制作门牌的方法是先制作0 到9 这几个数字字符,最后根据需要将字符粘贴到门牌上,例如门牌1017 需要依次粘贴字符1、0、1、7,即需要1 个字符0,2 个字符1,1 个字符7。
请问要制作所有的1 到2020 号门牌,总共需要多少个字符2?answer:624
#include <bits/stdc++.h>
using namespace std;
int cnt;
int main(){
int i,n;
for(i=1;i<=2020;i++){
n=i;
do{
if(n%10==2){
cnt++;
}
n=n/10;
}while(n!=0);
}
cout << cnt << endl;
return 0;
}
试题B:既约分数(欧几里得算法)
如果一个分数的分子和分母的最大公约数是1,这个分数称为既约分数。
例如,4/3 , 5/2 ,1/8 ,7/1都是既约分数。
请问,有多少个既约分数,分子和分母都是1到2020之间的整数(包括1 和2020)?answer:2481215
c++实现:
#include <bits/stdc++.h> using namespace std; int cnt; int main(){ int i,j; for(i=1;i<=2020;i++){ for(j=1;j<=2020;j++){ if(__gcd(i,j)==1){ cnt++; } } } cout << cnt << endl; return 0; }
c实现:
#include <stdio.h> int main(){ int cnt=0; int i,j,temi,temj,t,tem; for(i=1;i<=2020;i++){ for(j=1;j<=2020;j++){ temi=i,temj=j; if(temi<temj){ t=temi; temi=temj; temj=t; } while(temi%temj!=0){ tem=temi%temj; temi=temj; temj=tem; } if(temj==1)cnt++; } } printf("%d\n",cnt); return 0; }
试题C:蛇形填数
如下图所示,小明用从 1 开始的正整数 “蛇形” 填充无限大的矩阵。
容易看出矩阵第二行第二列中的数是 5,请你计算矩阵中第 20 行第 20 列的数是多少?
#include <bits/stdc++.h>
using namespace std;
int main(){
int r=1,c=1,i;
for(i=2;i<=1000;i++){
if((r+c)%2==0){
if(r==1){
c=c+1;
}else{
r=r-1;
c=c+1;
}
}
else{
if(c==1){
r=r+1;
}else{
r=r+1;
c=c-1;
}
}
if(r==20 && c==20)break;
}
cout << i << endl;
return 0;
}
试题D:跑步锻炼
小蓝每天都锻炼身体。正常情况下,小蓝每天跑 1 千米。如果某天是周一或者月初(1 日),为了激励自己,小蓝要跑 2 千米。如果同时是周一或月初,小蓝也是跑 2 千米。
小蓝跑步已经坚持了很长时间,从 2000 年 1 月 1 日周六(含)到 2020 年10 月 1 日周四(含)。请问这段时间小蓝总共跑步多少千米?
#include <bits/stdc++.h>
using namespace std;
int main(){
int D[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int week=6,y,m,d,cnt;
for(y=2000;y<=2020;y++){
if(y%4==0&&y%100!=0 || y%400==0){
D[2]=29;
}else{
D[2]=28;
}
for(m=1;m<=(y==2020?10:12);m++){
for(d=1;d<=(y==2020&&m==10?1:D[m]);d++){
if(week==1 || d==1){
cnt+=2;
}else{
cnt+=1;
}
week=(week+1)%7;
}
}
}
cout << cnt << endl;
return 0;
}
试题F:成绩统计
【问题描述】
小蓝给学生们组织了一场考试,卷面总分为 100 分,每个学生的得分都是一个 0 到 100 的整数。如果得分至少是 60 分,则称为及格。如果得分至少为 85 分,则称为优秀。
请计算及格率和优秀率,用百分数表示,百分号前的部分四舍五入保留整 数。
【输入格式】
输入的第一行包含一个整数 n,表示考试人数。接下来的n行,每行包含一个 0 至 100 的整数,表示一个学生的得分。
【输出格式】
输出两行,每行一个百分数,分别表示及格率和优秀率。百分号前的部分 四舍五入保留整数。【样例输入】
7
80
92
56
74
88
100
0
【样例输出】
71%
43%
【评测用例规模与约定】
对于50%的评测用例,1<=n<=100。
对于所有评测用例,1<=n<=10000。
#include <bits/stdc++.h>
using namespace std;
int main(){
int i,a,n,cnt1=0,cnt2=0;
int r1,r2,r3;
cin >> n;
for(i=0;i<n;i++){
cin >> a;
if(a>=85)cnt1++;
if(a>=60)cnt2++;
}
r1=(cnt1*100.0)/n+0.5;
r2=(cnt2*100.0)/n+0.5;
r3=3.3;
cout << r2 << "%\n" << r1 << "%\n" << endl;
return 0;
}
试题G:回文日期
2020 年春节期间,有一个特殊的日期引起了大家的注意:2020 年 2 月 2 日。因为如果将这个日期按 “yyyymmdd” 的格式写成一个 8 位数是 20200202,恰好是一个回文数。我们称这样的日期是回文日期。
有人表示 20200202 是 “千年一遇” 的特殊日子。对此小明很不认同,因为不到 2 年之后就是下一个回文日期:20211202 即 2021 年 12 月 2 日。
也有人表示 20200202 并不仅仅是一个回文日期,还是一个 ABABBABA 型的回文日期。对此小明也不认同,因为大约 100 年后就能遇到下一个 ABABBABA 型的回文日期:21211212 即 2121 年 12 月 12 日。算不上 “千年一遇”,顶多算 “千年两遇”。
给定一个 8 位数的日期,请你计算该日期之后下一个回文日期和下一个 ABABBABA 型的回文日期各是哪一天。
【输入格式】
输入包含一个八位整数 N,表示日期。【输出格式】
输出两行,每行 1 个八位数。第一行表示下一个回文日期,第二行表示下一个 ABABBABA 型的回文日期。
【样例输入】
20200202
【样例输出】
20211202
21211212【评测用例规模与约定】
对于所有评测用例,10000101≤N≤89991231,保证 N是一个合法日期的 8 位数表示。
#include <bits/stdc++.h>
using namespace std;
bool ok(string s);
bool check(int y);
int main(){
int D[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
string S,ans1="",ans2="";
cin >> S;
int i,m,d;
for(i=stoi(S.substr(0,4));ans1==""||ans2=="";i++){
string s=to_string(i),t=to_string(i);
reverse(t.begin(),t.end());
s=s+t;
m=stoi(s.substr(4,2)),d=stoi(s.substr(6,2));
if(check(i)){
D[2]=29;
}else{
D[2]=28;
}
if(s<=S) continue;
if(m<1||m>12) continue;
if(d<1||d>D[m]) continue;
if(ans1=="")ans1=s;
if(ok(s)&&ans2=="")ans2=s;
}
cout << ans1 << '\n' << ans2 << endl;
return 0;
}
bool ok(string s){
if(s[0]==s[2] && s[1]==s[4]){
return true;
}else{
return false;
}
}
bool check(int y){
if(y%4==0&&y%100!=0 || y%400==0){
return true;
}else{
return false;
}
}
试题H:子串分值和
【题目描述】
对于一个字符串 S SS,我们定义 S SS 的分值 f ( S ) f(S)f(S) 为 S SS 中出现的不同的字符个数。例如 f ( “ aba ” ) = 2,f(“abc”)=3,f(“aaa”)=1。现在给定一个字符串 S [ 0.. n − 1 ] (长度为n),请你计算对于所有 S 的非空子串 S [ i . . j ](0<=i<=j<n)f(S[i..j]) 的和是多少。
【输入格式】
输入一行包含一个由小写字母组成的字符串 S。【输出格式】
输出一个整数表示答案。【样例输入】
ababc【样例输出】
28【样例说明】
子串 f值
a 1
ab 2
aba 2
abab 2
ababc 3
b 1
ba 2
bab 2
babc 3
a 1
ab 2
abc 3
b 1
bc 2
c 1
暴力解法(运行超时,通过率40%)
#include <bits/stdc++.h>
using namespace std;
int main(){
string S;
cin >> S;
int l,r,k,n=S.size(),ans=0;
for(l=0;l<n;l++){
for(r=0;r<n;r++){
unordered_set<char> s;
for(k=r;k<=l;k++){
s.insert(S[k]);
}
ans+=s.size();
}
}
cout << ans << endl;
return 0;
}
正确解法
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int last[200];
ll ans;
int main(){
string S,s;
cin >> S;
s=" "+S;
int l,n=S.size();
for(l=1;l<=n;l++){
ans+=(ll)(l-last[s[l]])*(n-l+1);
last[s[l]]=l;
}
cout << ans << endl;
return 0;
}
试题I:平面切分
【问题描述】
平面上有 N 条直线,其中第 i 条直线是 y = Ai · x + Bi。
请计算这些直线将平面分成了几个部分。
【输入格式】
第一行包含一个整数 N。
以下 N 行,每行包含两个整数 Ai,Bi。
【输出格式】
一个整数代表答案。
【样例输入】
3
1 1
2 2
3 3
【样例输出】
6
【评测用例规模与约定】
对于 50% 的评测用例, 1 ≤ N ≤ 4, −10 ≤ Ai,Bi ≤ 10。
对于所有评测用例, 1 ≤ N ≤ 1000, −100000 ≤ Ai,Bi ≤ 100000。
#include <bits/stdc++.h>
using namespace std;
long long ans;
long double s[1000][2];
bool st[1000];
pair<long double,long double> p;
int main(){
int n,i,j;
cin >> n;
for(i=0;i<n;i++){
cin >> s[i][0] >> s[i][1];
set <pair<long double,long double> > points;
for(j=0;j<i;j++){
if(st[j]==1)continue;
if(s[i][0]==s[j][0]){
if(s[i][1]==s[j][1]){
st[i]=1;
break;
}else continue;
}
p.first=(s[j][1]-s[i][1])/(s[i][0]-s[j][0]);
p.second=s[i][0]*p.first+s[i][1];
points.insert(p);
}
if(st[i]==0)ans+=points.size()+1;
}
cout << ans+1 << endl;
return 0;
}