蓝桥杯2020年第十一届C/C++B组(第一次)省赛习题题解

目录

第一题:跑步训练(模拟)

第二题:纪念日(模拟)

第三题:合并检测(数学)

第四题 REPEAT 程序(模拟)

第五题:矩阵(dp)

第六题:整除序列(模拟)

第七题:解码(模拟+string)

第八题:走方格(DFS+dp)

第九题:整数拼接(数学+幂)


题目来源:2020年第十届C/C++ B组第一场蓝桥杯省赛真题_戎码一生的博客-CSDN博客_蓝桥杯c++真题


第一题:跑步训练(模拟)

 核心思路:

由于答案要求的是秒数,所以需要将上述的单位转换为秒,那么就可以得到平均每秒的能量损耗;因为有剩下的能量,不足以支撑1分钟的跑步的情况,所以需要对此情况进行特判

#include<iostream>

using namespace std;

int main()
{
	int n = 10000;
	int run = 600 / 60;//每秒的消耗 
	int time = 0;
	while (n)
	{

		if (n - 600 < 0)//如果剩余的能量不支撑于1分钟run,则取整秒break
		{
			time = time * 60 + n / run;
			break;
		}
		n -= 600;
		n += 300;
		time += 2;
	}
	cout << time;
	return 0;
}

第二题:纪念日(模拟)

 核心思路:

因为要求的是天数,平年365天,闰年366天,枚举天数的同时,特判平年还是闰年即可

#include<iostream>

using namespace std;

int yearDay(int year)
{
	if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
	{
		return 366;
	}
	return 365;
}

int main()
{
	int time = 0;
	for (int i = 1922; i <= 2020; i++)
	{
		time += yearDay(i);
	}
	time -= 22;//23-22=1
	cout << time * 24 * 60 << endl;
	return 0;
}

第三题:合并检测(数学)

 核心思路:

假设总人数为100人,那么就有,对于k枚举 1~100 的范围内

(1)对于 总人数100%k==0 的情况:需要的总的试剂盒为:(100/i)+ i

········解释:(100/i):100个人中每次分为i个人 为 1组,那么总共就分为了 100/i组

········解释: +i是因为 它有1%的阳性率,(概率呈均匀分布)那么这100个人中就必定有人为阳性,那么就需要对,患阳性的那一组重新进行i个人的检测

(2)对于 总人数100%k!=0 的情况:需要的总的试剂盒为:(100/i)+ 1 + i

········解释:对于除不尽的情况需要进行+1 处理,即被分为了(100/i)+1组,剩下的的解释就与上面相同

#include<iostream>

using namespace std;

int main()
{
	int ans = 0;
	int sum = 0x3f3f3f;//初始化为一个很大的数,因为要求的是小于的情况
	for (int i = 1; i <= 100; i++)//枚举所有的检测数 
	{
		if (100 % i == 0)
		{
			if (100 / i + i < sum)
			{
				sum = 100 / i + i;
				ans = i;//题目要求的是被分为多少组是最小的,所以需要进行记录
			}
		}
		else
		{
			if (100 / i + 1 + i < sum)
			{
				sum = 100 / i + 1 + i;
				ans = i;//记录当前最小的检测数
			}
		}
	}
	cout << ans << endl;
}

第四题 REPEAT 程序(模拟)

 核心思路:模拟

#include<iostream>

using namespace std;

int main()
{
	int ans = 0;
	for (int i = 0; i < 2; i++)
	{
		ans += 4;
		for (int j = 0; j < 5; j++)
		{
			for (int k = 0; k < 6; k++)
			{
				ans += 5;
			}
			ans += 7;
		}
		ans += 8;
	}
	ans += 9;
	cout << ans << endl;
	return 0;
}

第五题:矩阵(dp)

 思路来自:  

第十一届蓝桥杯 ——矩阵_六级不考550+不改名-CSDN博客

#include <iostream>
using namespace std;

int f[1020][1020];//含义:第一行中选i个数字,第二行中选择j个数字的方案数

int main()
{
    f[0][0] = 1;                                   // 两行一个数字都不放,也是一种方案
    for (int i = 0; i <= 1010; i++)
        for (int j = 0; j <= i; j++)
        {
            if (i - 1 >= j)                         // 转移前的状态也要合法,即第一行的数量不小于第二行的数量
                f[i][j] += f[i - 1][j] % 2020;
            if (j - 1 >= 0)
                f[i][j] += f[i][j - 1] % 2020;
        }

    cout << f[1010][1010] << endl;//全选的情况
    return 0;
}

第六题:整除序列(模拟)

#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
    long long n;
    scanf("%lld",&n);
    
    while(n)
    {
        printf("%lld ",n);
        n>>=1;
    }
    
    return 0;
}

第七题:解码(模拟+string)

 

#include <iostream>
#include <cstring> 
using namespace std;

int main()
{
	string s;
	cin >> s;
	
	string ans;
	for (int i = 0; i < s.size(); i ++)
	{
		if(s[i] >= '0' && s[i] <= '9')
			for (int j = 0; j < (s[i] - '0') - 1; j ++) ans += s[i - 1];
		else ans += s[i];
	}
	
	cout << ans << endl;
	return 0;
}

第八题:走方格(DFS+dp)

 

 思路来自:

第十一届蓝桥杯——走方格_六级不考550+不改名-CSDN博客

#include <iostream>
using namespace std;

const int N = 50;

int f[N][N];

int main()
{
	int n, m;
	cin >> n >> m;
				
	for (int i = 1; i <= n; i ++)
		for (int j = 1; j <= m; j ++)
		{
			if(i % 2 == 0 && j % 2 == 0) continue;
			
			if(i == 1 && j == 1) f[i][j] = 1;              // 起点到起点只有一种方案 
			else if(i == 1) f[i][j] = 1;                   // 第一行只能从左边走过来 
			else if(j == 1) f[i][j] = 1;                   // 第一列只能从上面走下来 
			else f[i][j] = f[i][j - 1] + f[i - 1][j];      // 其余情况:既能从左边走过来,也可以从上面走下来 
		}
		
	cout << f[n][m] << endl;
	return 0;
} 

第九题:整数拼接(数学+幂)

暴力:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
const int N = 100010;
int n, k;
int a[N];

bool check(int x,int y)
{
	int cnt = 0;
	int t = y;
	while (y)//123
	{
		cnt++;
		y /= 10;
	}
	x = x * pow(10, cnt) + t;

	if (x % k == 0) return true;
	else return false;
}

int main()
{
	cin >> n >> k;
	for (int i = 0; i < n; i++) scanf("%d", &a[i]);
	
	int ans = 0;
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			if (check(a[i], a[j]) && i!=j) ans++;
		}
	}

	cout << ans << endl;

	return 0;
}

优化:

AcWing 2068. 整数拼接 - AcWing

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

typedef long long ll;
const int N = 100010;

int n, mod;     // n 即题目中 n,mod 即上述 k
ll ans;         // ans 存答案,由于最多会有 n ^ 2 中情况,所以需要开 ll
int a[N];       // a 存输入数据
int cnt[11][N]; // cnt 即上述数组 cnt

int log_10(int x) // 返回 1 + log10(x)
{
    int res = 0;
    while (x) x /= 10, res ++ ;
    return res;
}

void work()     // 从前往后跑一遍
{
    for (int i = 0; i < n; i ++ )
    {
        ans += cnt[log_10(a[i])][(mod - a[i] % mod) % mod]; // 累加 cnt
        for (int j = 0, power = 1; j < 11; j ++ ) // 将 a[i] 的 0 ~ 10 次方 % mod 的结果计入 cnt
        {
            cnt[j][power * 1ll * a[i] % mod] ++ ;
            power = power * 10 % mod;
        }
    }
}

int main()
{
    scanf("%d%d", &n, &mod);
    for (int i = 0; i < n; i ++ )
        scanf("%d", a + i);

    work();

    memset(cnt, 0, sizeof cnt); // 别忘了在第二次跑之前清空一下 cnt 数组
    // 其实并不需要从前往后,从后往前写两遍。
    // 只需要将数组反转一下,再从前往后跑一遍即可
    reverse(a, a + n);

    work();

    printf("%lld\n", ans);
    return 0;
}

作者:垫底抽风
链接:https://www.acwing.com/solution/content/15969/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值