第十三届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组题解

5+5变2+8难度就上来了,感觉含金量会好一点

PS:线上除外,当这话没说就行

试题 A: 九进制转十进制

第十三届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组题解_第1张图片

 解析略,打卡题直接上代码

int x=2020;
while(x>=9){
    cout<

 试题 B: 顺子日期

 第十三届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组题解_第2张图片

 目前有很多争议,分为 3 种答案:4,5,14
我考试时写的答案是 4

而比赛后当天晚上的蓝桥云课说的是 14第二种答案:4

即认为 012 和逆序的顺子(如 210)都不算是顺子,因此把上面的 20220321 去掉

 第一种答案:4
即认为 012 和逆序的顺子(如 210)都不算是顺子,因此把 20220321 去掉

20220123
20221123
20221230
20221231

 第二种答案:14
题目说的顺子是:连续的三个数字,并不是三位数。所以 012 也算是顺子。再由第二个例子 20221023 得知:210 这种逆序的不算顺子。
如果要算上 012,那么第一个例子就把 210 这种逆序的给否掉

20220120
20220121
20220122
20220123
20220124
20220125
20220126
20220127
20220128
20220129
20221012
20221123
20221230
20221231

 试题 C: 刷题统计

第十三届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组题解_第3张图片

 先取余再暴力

#include 
using namespace std;

int main() {
	long long a, b, n;
	cin >> a >> b >> n;
	int week = 5 * a + 2 * b;
	long long ans = n / week * 7;
	n %= week;
	int sum = 0;
	for (int i = 1; i <= 7 && sum < n; i++) {
		if (i % 7 == 6 || i % 7 == 0) {
			sum += b;
		}
		else {
			sum += a;
		}
		ans++;
	}
	cout << ans << endl;
	return 0;
} 

 试题 D: 修剪灌木

 第十三届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组题解_第4张图片

// 暴力代码:来回走两次。注意回的时候要把两个边界去掉。

#include 
#include 
using namespace std;

const int maxn = 1e4 + 100;
int a[maxn];
int maxHeight[maxn];

int main() {
	int n;
	while (cin >> n) {
		memset(a, 0, sizeof(a));
		memset(maxHeight, 0, sizeof(maxHeight));
		
		// 来回走两次
		for (int today = 0; today < n; today++) {
			for (int i = 0; i < n; i++) {
				a[i]++;
				if (a[i] > maxHeight[i]) {
					maxHeight[i] = a[i];
				}
				if (i == today) {
					a[i] = 0;
				}
			}
		}
		for (int today = n - 2; today > 0; today--) {
			for (int i = 0; i < n; i++) {
				a[i]++;
				if (a[i] > maxHeight[i]) {
					maxHeight[i] = a[i];
				}
				if (i == today) {
					a[i] = 0;
				}
			}
		}
		for (int today = 0; today < n; today++) {
			for (int i = 0; i < n; i++) {
				a[i]++;
				if (a[i] > maxHeight[i]) {
					maxHeight[i] = a[i];
				}
				if (i == today) {
					a[i] = 0;
				}
			}
		}
		for (int today = n - 2; today > 0; today--) {
			for (int i = 0; i < n; i++) {
				a[i]++;
				if (a[i] > maxHeight[i]) {
					maxHeight[i] = a[i];
				}
				if (i == today) {
					a[i] = 0;
				}
			}
		}
		for (int i = 0; i < n; i++) {
			cout << maxHeight[i] << " ";
		}
		cout << endl << endl;
	}
	return 0;
}

试题 E: X 进制减法 

第十三届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组题解_第5张图片

 

要首先理解数字中每一位的权值。例如十进制中 123 的 1 权值为 1 0 2 10^210 2 ,表示 1 ∗ 1 0 2 = 100 1*10^2=1001∗10 2=100,而四进制中的 123 的 1 权值为 1 ∗ 4 2 = 16 1*4^2=161∗4 2 =16。

先将两个数字右对齐,然后从右边开始逐位进行减法操作。每一位的进制虽不相同,但是题目要求减法的结果最小,即两个数字尽量接近。位数一定时,如果进制大,则两个数字差距就大;如果进制小,则两个数字差距就小。所以我们应该让每一位的进制尽可能地小,但是又需要让数字合法,例如某一个数字是 5,那么这一位至少是六进制(5+1=6)。所以我们算出每一位的进制最小是多少,进行减法即可。

#include 
using namespace std;
const int mod = 1e9 + 7;
long long a[100001], b[100001];
int main(){
        int n, m1, m2;
        cin >> n >> m1;
        for(int i = 1; i <= m1; i++){
                cin >> a[i];
        }
        cin >> m2;
        for(int i = m1-m2+1; i <= m2; i++){ // 这里为了右对齐,所以 i 的起始值需要注意一下
                cin >> b[i];
        }
        long long val = 1, ans = 0;
        for(int i = m1; i >= 1; i--){
                int z = max(2, max(a[i], b[i]) + 1); // 算出最小进制,至少二进制,所以要求 max
                ans += (a[i] - b[i]) * val;
                ans %= mod;
                val = (val * z) % mod; // val 表示当前位的权值
        }
        cout << ans << endl;
        return 0;
}

试题 F: 统计子矩阵 

 第十三届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组题解_第6张图片

#include 
using namespace std;
long long a[505][505], sum[505][505];
long long n, m, kk;
bool check(int i, int j, int k, int mid){
        int now = sum[k][mid] - sum[i-1][mid] - sum[k][j-1] + sum[i-1][j-1];
        if(now <= kk)
                return true;
        else
                return false;
}
int main(){
        
        cin >> n >> m >> kk;
        for(int i = 1; i <= n; i++){
                for(int j = 1; j <= m; j++){
                        cin >> a[i][j];
                }
        }
        for(int i = 1; i <= n; i++){
                for(int j = 1; j <= m; j++){
                        sum[i][j] = sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1] + a[i][j];
                }
        }
        int res = 0;
        for(int i = 1; i <= n; i++){
                for(int j = 1; j <= m; j++){
                        for(int k = i; k <= n; k++){
                                int l = j, r = m,  ans=j-1;
                                while(l <= r){
                                        int mid = (l + r) >> 1;
                                        if(check(i,j,k,mid)){
                                                l = mid + 1;
                                                ans = mid;
                                        }else{
                                                r = mid - 1;
                                        }
                                }
                                 res += ans - j + 1; // ans 前面的都满足条件
                        }
                }
        }
        cout << res << endl;
        return 0;
}

试题 G: 积木画 

 第十三届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组题解_第7张图片

#include 
using namespace std;
const int maxn = 1e7 + 5;
const int mod = 1e9 + 7;
#define ll long long
ll dp[maxn],sum[maxn];
int main(){
        int n;
        cin >> n;
        dp[0] = 1;
        sum[0] = 1;
        for(int i = 1; i <= n; i++){
        		dp[i] = (dp[i] + dp[i-1] + dp[i-2]) % mod;
                if(i >= 3){
                	dp[i] = (dp[i] + 2 * sum[i-3]) % mod;
                }
                sum[i] = (sum[i-1] + dp[i]) % mod;
        }
        cout << dp[n];
        return 0;
}

试题 H: 扫雷

 第十三届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组题解_第8张图片

思路:DFS,待补 

 试题 I: 李白打酒加强版

第十三届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组题解_第9张图片 

 计数 d p ,注意如果李白的酒翻倍到超过 n  的时候,说明永远不可能消耗完这些酒。(因为这个题目想要的是在最终喝完所有酒,而每朵花只能消耗 1 单位的酒。)

#include 
using namespace std;
const int maxn = 1e7 + 5;
const int mod = 1e9 + 7;
#define ll long long
ll dp[201][201][201];
int main(){
        dp[0][2][0] = 1;
        int n, m;
        cin >> n >> m;
        n += m;
        for(int i = 0; i <= n-1; i++){
                for(int j = 0; j <= n; j++){
                        for(int k = 0; k <= m; k++){
                                if(j > n - i)        continue; // 重点,当酒的数量过多根本消耗不完的时候,不再转移
                                if(j != 0) // 遇到花
                                        (dp[i+1][j-1][k+1] += dp[i][j][k]) %= mod;        
                                if(j * 2 >= n || i == n-1){ // 最后一次必须是花,所以 i==n-1 时不进行后续转移
                                        continue;
                                }
                                (dp[i+1][j*2][k] += dp[i][j][k]) %= mod; // 翻倍
                        }
                }
        }
        cout << dp[n][0][m];
        return 0;
}

试题 J: 砍竹子  

 第十三届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组题解_第10张图片

是一个最长公共下降子序列问题,对于任意一个h,只要它高度降到了与前一个高度下降过程中的公共值,那么它就不需要花费代价继续下降。
如果它降得的当前高度与前一个高度没有公共值,则需要多花费一个代价,来降低自己的高度 

 

#include 
using namespace std;
typedef long long ll;
const int N=2e5+10;
ll a[N];
vectorb[N];
ll fun(ll x)
{
    return sqrt(x/2+1);
}
int main() {
    int n;
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    int ans= 0;
    for(int i=1;i<=n;i++) 
    {
        while(a[i]>1) 
        {
            int flag = 0;
            for(auto j : b[i-1])
            {
                if(a[i]==j) 
                {
                    flag=1;
                    break;
                }
            }
            if(!flag) ans++;
            b[i].push_back(a[i]);
            a[i]=fun(a[i]);
        }
    }
    cout<

你可能感兴趣的:(C++,笔记,蓝桥杯,蓝桥杯,c++,c语言,算法,动态规划)