第十一届蓝桥杯大赛软件类省赛第二场C/C++大学B组
试题A 门牌制作
答案为624
循环取余确定2的数目,代码如下
#include <iostream>
using namespace std;
int main()
{
int cnt = 0;
for (int i = 1; i <= 2020; i++)
{
for (int j=i;j > 0; j=j / 10)
{
if (j % 10 == 2)
{
cnt += 1;
}
}
}
cout<<cnt;
return 0;
}
试题B 既约分数
最大公约数gcd(a,b)=gcd(b,a%b) ,运用辗转相除法并进行递归操作,代码如下
#include <iostream>
using namespace std;
int gcd(int,int);
int main() {
int num = 0;
const int N = 2020;
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
if (gcd(i, j) == 1) {
num++;
}
}
}
cout << num;
return 0;
}
//最大公约数gcd(a,b)=gcd(b,a%b)
int gcd(int a, int b)
{
if (b==0)
return a;
return gcd(b, a%b);//递归
}
答案为2481215
试题C 蛇形填数
直接观察规律,数学手算。
要求第20行第20列,直接找对角线的规律,1,5,13,25.......可以看出对角线相邻两项的差形成等差数列,a1为4,d等于4,要求第20个对角线上的数,应该是1加上等差数列的前19项和,所以Sn=4*19+19*18*4/2=760,加上对角线首位1,答案为761
试题D 跑步锻炼
答案为8879
代码及思路如下
#include<iostream>
using namespace std;
int month[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int main() {
//初始化日期
int y = 2000, m = 1, d = 1, w = 6, km = 0;//年份,月份,日期,星期, 千米数
while (1) {
km += (d == 1 || w == 1) + 1;//千米数累加,一号或周一增加2
if (y == 2020 && m == 10 && d == 1) {
break;
}
w =( w + 1 ) % 7;
d = d + 1;//日期天数递增
if(( y % 400 == 0 || y % 4 == 0 && y % 100 != 0 ) && m == 2)
{//闰年且为二月
if (d > month[m] + 1)
{
d = 1;
m += 1;
}
}
else if (d > month[m])
{
d = 1;
m += 1;
}//天数循环,月数加一
if (m == 13)
{
y += 1;
m = 1;
}//月份循环,年数加一
}
cout<<km;
return 0;
}
试题E 七段码
从一个二维的数组深搜变成一个无向图,代码如下
#include <bits/stdc++.h>
#define MAX 7
using namespace std;
// 相邻数组
int a[MAX][MAX] = {0};
// 亮灯数组
int b[MAX] = {1, 1, 0, 1, 1, 1, 0};
// 映射数组
int c[MAX] = {0};
// 初始化图
void init()
{
a[0][1] = 1;
a[0][5] = 1;
a[1][2] = 1;
a[1][6] = 1;
a[2][3] = 1;
a[2][6] = 1;
a[3][4] = 1;
a[4][5] = 1;
a[4][6] = 1;
a[5][6] = 1;
}
// 深搜相邻的点并且关掉
void dfs(int k)
{
// 把k位置关掉
c[k] = 0;
for (int i = 0; i < MAX; i++)
{
// 若i位置与k位置相连
if (a[i][k] || a[k][i])
{
// 如果i位置亮着灯
if (c[i])
{
// 深搜
dfs(i);
}
}
}
}
bool check()
{
// 数组映射
for (int i = 0; i < MAX; i++)
{
c[i] = b[i];
}
int flag = 0;
for (int i = 0; i < MAX; i++)
{
// 如果i位置亮灯
if (c[i])
{
// 把他周围的灯全部灭掉
dfs(i);
// 连通块数+1
flag++;
}
}
// 如果全连着
if (flag == 1)
return true;
return false;
}
int main()
{
init();
int sum = 0;
// 可能亮1至7段
for (int i = 0; i < MAX; i++)
{
// 初始化亮灯数组
memset(b, 0, sizeof(b));
for (int j = 7; j >= i; j--)
{
b[j] = 1;
}
do
{
// 如果确实是一段
if (check())
sum++;
} while (next_permutation(b, b + MAX));
}
cout << sum;//结果为80
}
答案为80
试题F 成绩统计
代码如下
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
int n,a[10000]={0};
int cnt1=0,cnt2=0;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
for(int j=0;j<n;j++)
{
if(a[j]>=60){
cnt1++;
if(a[j]>=85)
{
cnt2++;
}
}
}
double d1, d2;
d1=cnt1/(n*1.0);
d2=cnt2/(n*1.0);
cout<<fixed<<setprecision(0)<<d1*100<<"%"<<endl;
cout<<fixed<<setprecision(0)<<d2*100<<"%"<<endl;
return 0;
}
试题G 回文日期
代码如下
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int days[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
bool check(int data)
{
int year=data/10000;
int month=(data/100)%100;
int day=data%100;
if(month<0 || month>12)
return false;
if(day==0 || month!=2 && day>days[month])
return false;
if(month==2)
{
int leap=(year%4==0 && year%100 !=0) || (year%400==0);
if(day>days[month]+leap)
return false;
}
return true;
}
int main()
{
int data;
int hui=0,abhui=0;
int flag1=0,flag2=0;
int s[9]={0};
int i,x;
cin>>data;
for(i=data+1;flag1==0||flag2==0;i++)
{
memset(s,0,8*sizeof(int));
if(check(i))
{
x=i;
for(int j=8;j>0;j--)
{
s[j]=x%10;
x=x/10;
}
//若flag==1,则无需更新
if(s[1]==s[8] && s[2]==s[7] &&s[3]==s[6] && s[4]==s[5] && flag1==0)
{
flag1=1;
hui=i;
}
//若flag==2,则无需更新
if(s[1]==s[3] &&s[1]==s[6] &&s[1]==s[8] && s[2]==s[4] && s[2]==s[5] && s[2]==s[7] && flag2==0)
{
flag2=1;
abhui=i;
}
}
}
cout<<hui<<endl<<abhui<<endl;
return 0;
}
运行结果
试题H 字串分值和
代码如下
#include <iostream>
using namespace std;
int main()
{
long long cnt=0;
int last[26]={};
string s;
cin>>s;
int n=s.length();
for(int i=1;i<=n;i++)
{
int j=s[i-1]-'a';
cnt+=(i-last[j])*(n-i+1);
last[j]=i;
}
cout<<cnt;
return 0;
}
运行结果
试题I 平面切分
代码如下
#include <bits/stdc++.h>
#define LL long long
using namespace std;
int main()
{
int N = 0;
int plans = 0;
cin >> N;
set<pair<double, double> > setab; //使用set来存储a b值对,会自动剔除重复的a b值
for(int i=0; i<N; i++){
pair<double, double> temp;
cin >> temp.first >> temp.second;
setab.insert(temp);
}
set<pair<double, double> >::iterator iter1 = setab.begin();
set<pair<double, double> > _setab; //不停的向其中添加直线
for(; iter1!=setab.end(); iter1++){
pair<double, double> temp = *iter1;
if(_setab.size() <= 0){//当前_setab集合为空则直接插入到该集合中
_setab.insert(temp);
plans = 2;
continue;
}
//将该直线与所有已有直线对比
double a1=temp.first, b1=temp.second;
double x, y;
double a2, b2;
set<pair<double, double> > setcp; //存储直线交点
set<pair<double, double> >::iterator iter2 =_setab.begin();
for(; iter2!=_setab.end(); iter2++){
a2=iter2->first; b2=iter2->second;
if(a1-a2 == 0){//平行则说明没有交点
_setab.insert(temp);
continue;
}
x=(b2-b1)/(a1-a2); y=(a1*b2-a2*b1)/(a1-a2);
setcp.insert(pair<double, double>(x, y));
}
//则增加的平面数量 = 与已有直线交点的个数 + 1
plans += (setcp.size()+1);
_setab.insert(temp);
}
cout << plans << endl;
return 0;
}
测试数据
试题J 字串排序
根据贪心算法,不断考虑重复字符的数量,代码如下
#include<iostream>
#include<vector>
using namespace std;
int getlen(int v) {
int i = 0;
while (v > 0) {
v -= i;
i++;
}
return i;
}
vector<int> nums;
int len;//预计最短字符串长度
void makenum(int w, int s) {
if (s == len) return;
int i = 1;
int t = 0;
while (1) {
if (len / i * t >= w) {
nums.push_back(i);
makenum(w - t, s + i);
break;
}
t += i;
i++;
}
}
int main() {
int v;
cin >> v;
len = getlen(v);//预计最短字符串长度
int m = 0;
for (int i = 0; i < len; i++) m += i; //该长度下最多交换次数;
makenum(m - v, 0);
char ch = 'a';
string ans = "";
for (int i : nums) {
//cout << i << endl;
for (int j = 0; j < i; j++) {
ans = ch + ans;
}
ch++;
}
cout << ans << endl;
return 0;
}
测试结果符合