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

记录刷题的过程、感悟、题解。
希望能帮到,那些与我一同前行的,来自远方的朋友😉


大纲:

 1、九进制转十进制-(解析)-简单的进制转化问题😄

 2、顺子日期-(解析)-考察日期

 3、刷题统计-(解析)-简单的除法问题🥲,千万别暴力,会超时

 4、修剪灌木-(解析)-真·贪心,主打一个观察能力🥲or 想象力

 5、X 进制减法-(解析)-进阶一点的进制转化,需要对进制转化,有更深层次的了解。

 6、统计子矩阵-(解析)-二维前缀和+滑动窗口,如果纯前缀和打暴力(只能过70%) 

 7、积木画-(解析)-太好了,我一直以为无解,原来能用线性dp做出来,太感动了(┬┬﹏┬┬),原来还能让人做。

 8、扫雷-(解析)-啊,这道题出乎意料的简单,出在倒数第三题,简直了😇,很多人都做不到呐。

 9、李白打酒加强版-(解析)-记忆化搜索+dfs,单纯dfs定超时。|| dp也能解决。

 10、砍竹子-(解析)-这道题真是智者见智了,八仙过海、各显神通。我用的优先队列。😉


题目:

1、九进制转十进制

问题描述

本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。

九进制正整数 (2022)9转换成十进制等于多少?

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 512M

本题就是一道,简单的进制转化题目

解析:(2022)9=2*9^0+2*9^1+0*9^2+2*9^

2是基数、9是进制数

#include <bits/stdc++.h>
using namespace std;
int main(){string str="2022";reverse(str.begin(),str.end());int sum=0;for(int i=0; i<str.size(); ++i){sum+=pow(9,i)*(str[i]-'0');}cout<<sum<<endl;return 0;
} 

2、顺子日期

问题描述

本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。

小明特别喜欢顺子。顺子指的就是连续的三个数字:123、456 等。顺子日期指的就是在日期的 yyyymmdd 表示法中,存在任意连续的三位数是一个顺子的日期。例如 20220123 就是一个顺子日期,因为它出现了一个顺子:123; 而 20221023 则不是一个顺子日期,它一个顺子也没有。小明想知道在整个 2022 年份中,一共有多少个顺子日期?

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 512M

本题,就写简单一点吧:"2022" 已经不可能与任何数 形成顺子了,可以直接排除掉

bool get_num(...)是用来判断,月日是否合理

bool get_cnt(...)是用来判断是否是顺子

#include <bits/stdc++.h>
using namespace std;
bool get_num(int mm, int dd){if(mm==1||mm==3||mm==5||mm==7||mm==8||mm==10||mm==12){// 31 天if(dd>=1&&dd<=31) return true;}else if(mm==2){ // 28天if(dd>=1&&dd<=28) return true;}else if(mm==4||mm==6||mm==9||mm==11){ // 30天if(dd>=1&&dd<=30) return true;} return false;
}bool get_cnt(string str){str = "9"+str; // 前面后缀一个数 vector<int> arr(str.size(),0);for(int i=1; i<str.size(); ++i)if(str[i]==str[i-1]+1) arr[i]=arr[i-1]+1; for(int i=1; i<arr.size(); ++i) if(arr[i]==2) return true;return false;
}int main()
{int sum=0;// 暴力。0100-1299 // 这些的吗?其实也能用递归深搜 for(int i=0; i<10; ++i){for(int j=0; j<10; ++j){for(int k=0; k<10; ++k){for(int z=0; z<10; ++z){ // 一共10层循环int mm = i*10+j;int dd = k*10+z;if(get_num(mm,dd)){string str =  to_string(i)+to_string(j)+to_string(k)+to_string(z);if(get_cnt(str)) sum++;}}}}}cout<<sum<<endl;return 0;
}

3、刷题统计

问题描述

小明决定从下周一开始努力刷题准备蓝桥杯竞赛。他计划周一至周五每天 做 a 道题目, 周六和周日每天做 b 道题目。请你帮小明计算, 按照计划他将在 第几天实现做题数大于等于 n 题?

输入格式

输入一行包含三个整数 a,b 和 n.

输出格式

输出一个整数代表天数。

样例输入

10 20 99

样例输出

8

评测用例规模与约定

对于 50% 的评测用例, 1≤a,b,n≤10^6.

对于 100% 的评测用例, 1≤a,b,n≤10^18.

// 哦草!本题大意了,没有看数据10^18次方呐,直接就开始暴力了。
// 本题没有必要开一个循环,一个一个加
// 能直接进行除法运算

#include <bits/stdc++.h>
#define int long long 
using namespace std;signed main(){int a,b,n;cin>>a>>b>>n;int cnt = 0;int sum = n/(a*5+b*2);int temp = n%(a*5+b*2);if(temp<=a*5){cnt+=ceil((double)temp/a);	}else{temp-=5*a;cnt+=5;cnt+=ceil((double)temp/b);}  cnt+=sum*7;cout<<cnt<<endl;return 0;
}   

4、修剪灌木

问题描述

爱丽丝要完成一项修剪灌木的工作。

有 N 棵灌木整齐的从左到右排成一排。爱丽丝在每天傍晩会修剪一棵灌 木, 让灌木的高度变为 0 厘米。爱丽丝修剪灌木的顺序是从最左侧的灌木开始, 每天向右修剪一棵灌木。当修剪了最右侧的灌木后, 她会调转方向, 下一天开 始向左修剪灌木。直到修剪了最左的灌木后再次调转方向。然后如此循环往复。

灌木每天从早上到傍晩会长高 1 厘米, 而其余时间不会长高。在第一天的 早晨, 所有灌木的高度都是 0 厘米。爱丽丝想知道每棵灌木最高长到多高。

输入格式

一个正整数 N, 含义如题面所述。

输出格式

输出 N 行, 每行一个整数, 第 i 行表示从左到右第 i 棵树最高能长到多高。

样例输入

3

样例输出

4
2
4

评测用例规模与约定

对于 30% 的数据, N≤10.

对于 100% 的数据, 1<N≤10000.

// 本题大意了,其实挺好解决的。
// 最开始,我傻傻的,造了三个循环去解决本题,好愚蠢的呢,简单题,做麻烦 
// 其实脑子里面模拟一下,前面割着草,后面长着草,是不是有画面感了
// 一共n颗灌木,到第i颗灌木时:(n-i-1)*2 or i*2 颗 --取最大 
// 只是两个方向,从左向右时:i*2
//              从右向左时:(n-i-1)*2

#include <bits/stdc++.h>
using namespace std;int main(){int n;cin>>n;vector<int> res(n,0);for(int i=0; i<n; ++i){res[i]=max(i*2,(n-i-1)*2);}for(int i:res) cout<<i<<endl;return 0;
}

5、X 进制减法

问题描述

进制规定了数字在数位上逢几进一。

X 进制是一种很神奇的进制, 因为其每一数位的进制并不固定!例如说某 种 X 进制数, 最低数位为二进制, 第二数位为十进制, 第三数位为八进制, 则 X 进制数 321 转换为十进制数为 65 。

现在有两个X 进制表示的整数 A 和 B, 但是其具体每一数位的进制还不确 定, 只知道 A 和 B 是同一进制规则, 且每一数位最高为 N 进制, 最低为二进 制。请你算出 A−B 的结果最小可能是多少。

请注意, 你需要保证 A 和 B 在 X 进制下都是合法的, 即每一数位上的数 字要小于其进制。

输入格式

第一行一个正整数 N, 含义如题面所述。

第二行一个正整数 Ma, 表示 X 进制数 A 的位数。

第三行 Ma​ 个用空格分开的整数, 表示 X 进制数 A 按从高位到低位顺序各 个数位上的数字在十进制下的表示。

第四行一个正整数 Mb​, 表示 X 进制数 B 的位数。

第五行 Mb​ 个用空格分开的整数, 表示 X 进制数 B 按从高位到低位顺序各 个数位上的数字在十进制下的表示。

请注意, 输入中的所有数字都是十进制的。

输出格式

输出一行一个整数, 表示 X 进制数 A−B 的结果的最小可能值转换为十进 制后再模 1000000007 的结果。

样例输入

11
3
10 4 0
3
1 2 0

样例输出

94

样例说明

当进制为: 最低位 2 进制, 第二数位 5 进制, 第三数位 11 进制时, 减法 得到的差最小。此时 A 在十进制下是 108, B 在十进制下是 14 , 差值是 94。

评测用例规模与约定

对于 30% 的数据, N≤10; Ma,Mb≤8.

对于 100% 的数据, 2≤N≤1000;1≤Ma​,Mb​≤100000;A≥B.

// 这是一道贪心题,读清楚题目之后,本题思路就会异常清晰。
// “两个数,共用一套X进制的规则”
// 质保保证两个数,尽可能的小就行
// 本题最重要的就是,进制转换的计算,
//(本位,前方所有进制相乘,就是此位置该乘的数)--> 举例:10*(2*5)+4*(2)+0*(0)=108 

#include <bits/stdc++.h>
#define int long long
const int CNT = 1000000007; 
using namespace std;signed main(){int N;cin>>N;int an,bn;cin>>an;vector<int> A(an,0);for(int i=an-1; i>=0; --i) cin>>A[i];cin>>bn;vector<int> B(bn,0);for(int j=bn-1; j>=0; --j) cin>>B[j];int sum = 0;int X = 1;for(int i=0; i<an; ++i){sum=(sum+(A[i]-B[i])*X)%CNT;X *= max(A[i],B[i])<=1?2:max(A[i],B[i])+1;X%=CNT;}cout<<sum<<endl;return 0;
} 

6、统计子矩阵

问题描述

给定一个 N×M 的矩阵 A, 请你统计有多少个子矩阵 (最小 1×1, 最大 N×M) 满足子矩阵中所有数的和不超过给定的整数 K ?

输入格式

第一行包含三个整数 N,M 和 K.

之后 N 行每行包含 M 个整数, 代表矩阵 A.

输出格式

一个整数代表答案。

样例输入

3 4 10
1 2 3 4
5 6 7 8
9 10 11 12

样例输出

19

样例说明

满足条件的子矩阵一共有 19 , 包含:

大小为 1×1 的有 10 个。

大小为 1×2 的有 3 个。

大小为 1×3 的有 2 个。

大小为 1×4 的有 1 个。

大小为 2×1 的有 3 个。

评测用例规模与约定

对于 30% 的数据, N,M≤20.

对于 70% 的数据, N,M≤100.

对于 100%的数据, 1≤N,M≤500;0≤Aij≤1000;1≤K≤250000000

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 256M

本质上就是一道二维前缀和+滑动窗口的集合,如果只用二维前缀和的话只能过70%

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 5e2 + 5;
int arr[N][N]; 
int n, m, K;signed main() {// 输入矩阵的行数、列数和阈值 Kcin >> n >> m >> K;// 输入矩阵元素for (int i = 1; i <= n; ++i)for (int j = 1; j <= m; ++j)cin >> arr[i][j];// 计算每行的前缀和for (int i = 1; i <= n; ++i)for (int j = 1; j <= m; ++j)arr[i][j] += arr[i][j - 1];// 计算每列的前缀和,得到二维前缀和for (int j = 1; j <= m; ++j)for (int i = 1; i <= n; ++i)arr[i][j] += arr[i - 1][j];int cnt=0;// 上边界 for(int top=0; top<=n; ++top){// 下边界 for(int bott=top+1; bott<=n; ++bott){// 左上边界 int l=0; // 右上边界 for(int r=1; r<=m; ++r){int sum= arr[bott][r]-arr[bott][l]-arr[top][r]+arr[top][l];	while(sum>K&&l<r){l++;sum= arr[bott][r]-arr[bott][l]-arr[top][r]+arr[top][l];}cnt+=r-l;}}	}// 输出结果cout << cnt << endl;return 0;
}    

7、积木画

问题描述

小明最近迷上了积木画, 有这么两种类型的积木, 分别为 I 型(大小为 2 个单位面积) 和 L 型 (大小为 3 个单位面积):

同时, 小明有一块面积大小为 2×N 的画布, 画布由 2×N 个 1×1 区域构成。小明需要用以上两种积木将画布拼满, 他想知道总共有多少种不同的方式? 积木可以任意旋转, 且画布的方向固定。

输入格式

输入一个整数 N,表示画布大小。

输出格式

输出一个整数表示答案。由于答案可能很大,所以输出其对 1000000007 取模后的值。

样例输入

3

样例输出

5

样例说明

五种情况如下图所示,颜色只是为了标识不同的积木:

评测用例规模与约定

对于所有测试用例,1≤N≤10000000.

运行限制

  • 最大运行时间:3s
  • 最大运行内存: 512M

注:其实很久很久之前,我是很恐惧这种题型的,因为我觉得无解
        现在发现,竟然能用动态规划解决,那实在太幸福了。毕竟难总比无解好

// 很多人说,本题是状态压缩,其实按照线性dp的思路就能解决。
// 说到动态规划,大家都清楚,是由前方状态推出后方状态
// 当然啦,还有每个状态的意义,状态推导公式、初始化,遍历顺序
/*
    每个状态的意义:!!一定要看清楚 
    dp[i][0] ,第i列,只有第一行被填满
    dp[i][2] ,第i列,只有第二行被填满
    dp[i][1] ,第i列,两整行都被填满 
*/ 
/*
    状态推导公式:
    dp[i][0]
    如果要使第一行能被填满,有两种可能,上一列为dp[i-1][2],于是可以横放一个I型
     还有一种可能是,上上一列 为dp[i-2][1],这种情况下,可以放置一个L型   
     于是推导出 dp[i][0]= dp[i-1][2]+dp[i-2][1];
     
     dp[i][2]
     上一列为dp[i-1][0],上一列,第一行有东西,此刻,就能横向放置I型
    上上一列为dp[i-2][1],这种情况下,可以放置一个L型 
    于是推导出 dp[i][2]=dp[i-1][0]+dp[i-2][1];
    
    dp[i][1]
    本列想要填满,只有可能为dp[i-1][0] or dp[i-1][2],本列可以放置L型
    dp[i-1][1](上一列被填满),本列可以放置I型
    dp[i-2][1](上上一列被填满),那可以置换成两个L型 
    dp[i][1]=dp[i-1][0] + dp[i-1][2] + dp[i-1][1] + dp[i-2][1];
*/ 

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MOD = 1000000007; 
const int N = 1e7+5;
// vector<vector<int>> dp(N,vector<int>(3,0));
int dp[N][3];signed main(){int n;cin>>n;	dp[0][1]=1; // 只能竖放一个I dp[1][1]=1; // 只能竖放一个I ,这个才是真正的第一列。for(int i=2; i<=n; ++i){dp[i][0]=(dp[i-1][2]+dp[i-2][1])%MOD;dp[i][2]=(dp[i-1][0]+dp[i-2][1])%MOD;dp[i][1]=((dp[i-1][0] + dp[i-1][2])%MOD + (dp[i-1][1] + dp[i-2][1])%MOD)%MOD;} cout<<dp[n][1]<<endl;return 0;
} 

8、扫雷

题目描述

在一个 n 行 m 列的方格图上有一些位置有地雷,另外一些位置为空。

请为每个空位置标一个整数,表示周围八个相邻的方格中有多少个地雷。

输入描述

输入的第一行包含两个整数 n,m。

第 2 行到第 n+1 行每行包含 m 个整数,相邻整数之间用一个空格分隔。如果对应的整数为 0,表示这一格没有地雷。如果对应的整数为 1,表示这一格有地雷。

其中,1≤n,m≤100 分钟后还是在当天。

输出描述

输出 n 行,每行 m 个整数,相邻整数之间用空格分隔。

对于没有地雷的方格,输出这格周围的地雷数量。对于有地雷的方格,输出 9。

输入输出样例

示例 1

输入

3 4
0 1 0 0
1 0 1 0
0 0 1 0

输出

2 9 2 1
9 4 9 2
1 3 9 2

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 128M

本题意想不到的简单,我人傻了。 

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e2+5;
vector<vector<int>> arr(N,vector<int>(N,0));
// 看到这道题目,我有点炸了,这道题目,咋这么简答😥,不是哥们,这可是倒数第三题呢。
//int arr[N][N];
//int res[N][N];
vector<vector<int>> res(N,vector<int>(N,0));
int n,m;
int fa1[]={1,1,0,0,-1,1,-1,-1};
int fa2[]={-1,1,1,-1,0,0,1,-1};signed main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);cin>>n>>m;for(int i=1; i<=n; ++i)for(int j=1; j<=m; ++j) cin>>arr[i][j];// 真嘟假嘟for(int i=1; i<=n; ++i){for(int j=1; j<=m; ++j){if(arr[i][j]!=0) res[i][j]=9;else{int sum=0;for(int k=0; k<8; ++k){if(arr[i+fa1[k]][j+fa2[k]]!=0) sum++;}res[i][j]=sum;}}}for(int i=1; i<=n; ++i){for(int j=1; j<=m; ++j) cout<<res[i][j]<<" ";cout<<endl;}return 0;
}

9、李白打酒加强版

问题描述

话说大诗人李白, 一生好饮。幸好他从不开车。

一天, 他提着酒显, 从家里出来, 酒显中有酒 2 斗。他边走边唱:

无事街上走,提显去打酒。 逢店加一倍, 遇花喝一斗。

这一路上, 他一共遇到店 N 次, 遇到花 M 次。已知最后一次遇到的是花, 他正好把酒喝光了。

请你计算李白这一路遇到店和花的顺序, 有多少种不同的可能?

注意: 显里没酒 ( 0 斗) 时遇店是合法的, 加倍后还是没酒; 但是没酒时遇 花是不合法的。

输入格式

第一行包含两个整数 N 和 M.

输出格式

输出一个整数表示答案。由于答案可能很大,输出模 1000000007 的结果.

样例输入

5 10

样例输出

14

样例说明

如果我们用 0 代表遇到花,1 代表遇到店,14 种顺序如下:

010101101000000

010110010010000

011000110010000

100010110010000

011001000110000

100011000110000

100100010110000

010110100000100

011001001000100

100011001000100

100100011000100

011010000010100

100100100010100

101000001010100

评测用例规模与约定

对于 40% 的评测用例: 1≤N,M≤10。

对于 100% 的评测用例: 1≤N,M≤100 。

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 256M
记忆化搜索+递归
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MOD = 1000000007;
int used[105][105][105]; 
int n,m,drink;
// 不论是递归,还是动规,都是推到至,上一种状态 
int dfs(int n,int m,int drink){if(n<0||m<0||drink<0) return 0;if(drink>m) return 0;if(n==0&&m==1&&drink==1) return 1; // 一切刚刚好 // 记忆化搜索 if(used[n][m][drink]!=-1) return used[n][m][drink]; // 记忆化搜索,代表遍历过 else {return used[n][m][drink]=(dfs(n-1,m,drink*2)+dfs(n,m-1,drink-1))%MOD; }}
signed main(){cin>>n>>m;memset(used,-1,sizeof used); // 统一初始化,助力记忆化搜索 drink = 2;cout<<dfs(n,m,drink); return 0;
}
动态规划
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MOD = 1000000007;
int n,m;
int dp[105][105][105];signed main(){cin>>n>>m;// 初始状态是:经过了0家店、0家花、有2壶酒。// 其实,就是由两个状态推导出来的/** dp[n][m][k]: 酒店 dp[n-1][m][drink/2] 他的上一种状态,可能已经经过n-1店、m家花、拥有drink/2个酒* dp[n][m][k]:花店 dp[n][m-1][drink+1] 他的上一种状态,可能经过n家店、m-1家花、拥有drink+1杯酒*/dp[0][0][2]=1; // 这是一种可能for(int i=0; i<=n; ++i){for(int j=0; j<=m; ++j){ for(int k=0; k<=m; ++k){if(j>0 && k>0) dp[i][j][k]=dp[i][j-1][k+1];if(i>0 && k%2==0) dp[i][j][k]=(dp[i][j][k]+dp[i-1][j][k/2])%MOD;}}}cout<<dp[n][m-1][1]<<endl;return 0;
}

10、砍竹子

问题描述

这天, 小明在砍竹子, 他面前有 n 棵竹子排成一排, 一开始第 i 棵竹子的 高度为 hi​.

他觉得一棵一棵砍太慢了, 决定使用魔法来砍竹子。魔法可以对连续的一 段相同高度的竹子使用, 假设这一段竹子的高度为 H, 那么

用一次魔法可以 把这一段竹子的高度都变为 ⌊⌊H2⌋+1⌋, 其中 ⌊x⌋ 表示对 x 向下取整。小明想 知道他最少使用多少次魔法可

让所有的竹子的高度都变为 1 。

输入格式

第一行为一个正整数 n, 表示竹子的棵数。

第二行共 n 个空格分开的正整数 hi​, 表示每棵竹子的高度。

输出格式

一个整数表示答案。

样例输入

6
2 1 4 2 6 7

样例输出

5

样例说明

// 灵感:暴力解法,去最大,找连续,并及时删除 
// 我忘记了,向上取整,是个啥玩意?? 
// 哪我就斗胆,用一次优先队列,在具体看一下,优先队列的用法
/*
  本题,其实最抽象的就是sqrtl---应用,因为本题最大特色就是,数字有10^18次方这么大,而double只用10^16~17这么大。
  为啥本题我选择了优先队列!毕竟本题是一道贪心题,找规则呗,下方样例说明中,提示,竹子,是从最高处开始砍的。
  优先队列不就是这么玩的吗😄?
  然后,又因为能使用魔法(本质就是,坐标相邻,大小相同的数组....
  所以一看就要引入pair<int,int>,当然struct也行。两者构造的时间与占用的空间都差不多。
  本来我还以为本题,需要用到双向队列(模拟)呢,不过,没想到这是一道中等题,没考的那么深
  此外,本题你需要重载一下priority_queue;
  好了,说正题
  本题在插入获取数据的时候,会遇到两种情况
  1、一连串相同的,共需用一次魔法
  2、遇到最大的,砍一次,需用一次魔法
  3、还有在遇到1时,直接弹出队列。不需要用到魔法。
  具体实现方式,在下方的😉
*/

#include <bits/stdc++.h>
#define int long long
#define x first
#define y secondusing namespace std;struct cmp{bool operator()(const pair<int,int>& p1,const pair<int,int>& p2){if(p1.x==p2.x) return p1.y>p2.y; // 小顶堆return p1.x<p2.x; // 不改变符号时,默认为大顶堆  }	
};int get_res(int cnt){ // 本题的公式,化简 return floor(sqrtl(floor(double(cnt)/2)+1));
}signed main(){priority_queue<pair<int,int>,vector<pair<int,int>>,cmp> pq;int n;cin>>n;for(int i=0; i<n; ++i){int num;cin>>num;pq.emplace(num,i);	}int cnt=0;int temp_id=-2,temp_cnt=-2;while(!pq.empty()){ // 优先队列不为空auto cur = pq.top();pq.pop(); // 直接删除 if(cur.x==1) continue;if(temp_id==cur.y-1&&temp_cnt==cur.x){// 当是下一个相同的值的时候temp_id=cur.y; int val = get_res(cur.x); if(val!=1) pq.emplace(val,temp_id);}else{// 这是一个新的不同的数值cnt++;temp_cnt=cur.x;temp_id =cur.y;int val = get_res(cur.x);if(val!=1) pq.emplace(val,temp_id);}} cout<<cnt;return 0;
} 

知识点

一、double 与 long double

double 
  • 大小:通常占用 8字节(64位)
  • 十进制取值范围:有效位数 约为15~17位
long double
  • 大小:有编译器决定,标准规定不少于double
    但是,在某些编辑器,与double占用的字节(8字节)是相同的
            在GCC编辑器的x86_64架构下,可能占12字节(96位);
            甚至在部分平台占用16字节(128位)(拓展进度)
  • 十进制取值范围:通常比double更大,通常有效位数18-19位

二、揭开 C++ 数学函数后缀的神秘面纱:fl 与精度战争

1、绝对值函数
  • fabs(double x) 计算double类型的绝对值
  • fabsf(float x) 计算float类型的绝对值
  • fabsl(long double x) 计算long double 类型的绝对值
2、取整函数
向上取整
  • ceil(double x) :对double向上取整
  • ceilf(float x):对float向上取整
  • ceill(long double x):对long double向上取整
向下取整

floor(double x)、floor(float x)、floor(long double x)。

四舍五入

round、roundf、roundl

3、开方

sqrt(double x)、sqrtf(float x)、sqrtl(long double x)

4、指数对数函数

三、不用+号的,加法

给出两个整数 a 和 b , 求他们的和并以整数(int)的形式返回。不能使用 + 等数学运算符。

样例

输入:

a = 1
b = 2
输出:

3

其实,这个是根据位运算^(存不进位的结果)与&(存进位的结果)

#include <iostream>
using namespace std;
int main(){int a=5;int b=3;int temp_a,temp_b;while(b!=0){temp_a = a^b; // 存放 不进位数 temp_b = a&b; // 仅存放 进位数 temp_b<<=1; // 将 进位的结果 右移 a=temp_a;b=temp_b; }cout<<a;return 0;
} 

四、状态压缩动态规划

五、为什么二维 vector 在 C++ 中慢如蜗牛?—— 数组与 vector 的性能对决

1、内存分配方式

vector<vector<int>> 

  • 这是一个二维动态数组,每个内部的vector单独分配内存。内存的分布是非连续的
  • 访问代价大,不同vector之间非连续,内存命中率低,会降低访问速度。

int arr[n][m]

  • 内存是连续的,直接分配一个n*m大小的内存,访问元素时缓存利用率高,性能更优。
  • 查找内存也非常方便,(i,j)--base+i*m+j,无序跳跃式访问。
2、初始化开销

vector<vector<int>> 

  • 在初始化时,需要多次调用构造器,去构造vector。 

int arr[n][m]

  • 全局或静态声明的数组,在程序刚启动时直接就能初始化,无需运行时开销。
3、扩容代价

vector

  • 当容量不够时,会扩容,然后复制拷贝。
  • 内存碎片化增加,影响后续分配效率。

静态数组

  • 大小固定,无扩容问题
4、内存占用

vector中,有各种额外元素(size、capacity、allocator等),占用内存更高。

静态数组,只是存储容量。

六、memset与sizeof

memset

C 库函数 void *memset(void *str, int c, size_t n) 用于将一段内存区域设置为指定的值。

memset() 函数将指定的值 c 复制到 str 所指向的内存区域的前 n 个字节中,这可以用于将内存块清零或设置为特定值。

在一些情况下,需要快速初始化大块内存为零或者特定值,memset() 可以提供高效的实现。

在清空内存区域或者为内存区域赋值时,memset() 是一个常用的工具函数。

重点!!通常memset是对每一个字节赋值,所以分配时,只能分配0 or -1(负一的补码为:1111)。-1用来赋值,0一般是用来清空。

void *memset(void *str, int c, size_t n)
  • str -- 指向要填充的内存区域的指针。
  • c -- 要设置的值,通常是一个无符号字符。
  • n -- 要被设置为该值的字节数。
#include <bits/stdc++.h>
using namespace std;
int main(){int arr[2][4];cout<<sizeof(arr)<<endl;cout<<sizeof(arr[0])<<endl;cout<<sizeof(arr[0])/sizeof(arr[0][0])<<endl;memset(arr,-1,sizeof(arr));cout<<arr[1][1];return 0;
} 
--------------------------------
32
16
4
-1
--------------------------------
sizeof

通过上述的例子,应该就能看出,sizeof求的是字节数。


如果更好的建议、请留言,我会 一 一查看。( •̀ ω •́ )✧

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/35.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux红帽:RHCSA认证知识讲解(十 二)调试 SELinux,如何管理 SELinux 的运行模式、安全策略、端口和上下文策略

Linux红帽&#xff1a;RHCSA认证知识讲解&#xff08;十 二&#xff09;调试 SELinux&#xff0c;如何管理 SELinux 的运行模式、安全策略、端口和上下文策略 前言一、SELinux 简介二、SELinux 的运行模式2.1 查看和切换 SELinux 模式 三、SELinux 预设安全策略的开关控制四、管…

Spring Cloud之服务入口Gateway之Route Predicate Factories

目录 Route Predicate Factories Predicate 实现Predicate接口 测试运行 Predicate的其它实现方法 匿名内部类 lambda表达式 Predicate的其它方法 源码详解 代码示例 Route Predicate Factories The After Route Predicate Factory The Before Route Predicate Fac…

下载安装Node.js及其他环境

提示&#xff1a;从Node版本降级到Vue项目运行 文章目录 下载Node.js环境配置配置环境变量 安装 cnpm&#xff08;我需要安装&#xff09;安装脚手架安装依赖安装淘宝镜像&#xff08;注意会更新&#xff09;cnpm vs npm 与新旧版本核心差异包管理器不同功能差异如何选择&#…

C++抽卡模拟器

近日在学校无聊&#xff0c;写了个抽卡模拟器供大家娱乐。 代码实现以下功能&#xff1a;抽卡界面&#xff0c;抽卡判定、动画播放、存档。 1.抽卡界面及判定 技术有限&#xff0c;不可能做的和原神一样精致。代码如下&#xff08;注&#xff1a;这不是完整代码&#xff0c;…

Redis 热key问题怎么解决?

Redis 热 Key 问题分析与解决方案 热 Key(Hot Key)是指被高频访问的某个或多个 Key,导致单个 Redis 节点负载过高,可能引发性能瓶颈甚至服务崩溃。以下是常见原因及解决方案: 1. 热 Key 的常见原因 突发流量:如明星八卦、秒杀商品、热门直播等场景。缓存设计不合理:如全…

第十四届蓝桥杯省赛真题解析(含C++详细源码)

第十四届蓝桥杯省赛 整数删除满分思路及代码solution1 &#xff08;40% 双指针暴力枚举&#xff09;solution 2&#xff08;优先队列模拟链表 AC&#xff09; 冶炼金属满分代码及思路 子串简写满分思路及代码solution 1&#xff08;60% 双指针&#xff09;solution 2&#xff0…

Matlab:三维绘图

目录 1.三维曲线绘图命令&#xff1a;plot3 实例——绘制空间直线 实例——绘制三角曲线 2.三维曲线绘图命令&#xff1a;explot3 3.三维网格命令&#xff1a;mesh 实例——绘制网格面 实例——绘制山峰曲面 实例——绘制函数曲线 1.三维曲线绘图命令&#xff1a;plot3 …

(51单片机)独立按键控制流水灯LED流向(独立按键教程)(LED使用教程)

源代码 如上图将7个文放在Keli5 中即可&#xff0c;然后烧录在单片机中就行了 烧录软件用的是STC-ISP&#xff0c;不知道怎么安装的可以去看江科大的视频&#xff1a; 【51单片机入门教程-2020版 程序全程纯手打 从零开始入门】https://www.bilibili.com/video/BV1Mb411e7re?…

React框架的Concurrent Mode

以下是关于 Concurrent Mode 的系统梳理: 一、Concurrent Mode 的诞生背景 传统渲染的局限性 同步阻塞:React 15 的 Stack Reconciler 无法中断渲染流程优先级缺失:用户交互与后台任务同等对待资源竞争:网络请求与渲染任务无法智能调度核心设计目标 可中断渲染:允许高优先…

Java 集合框架与 Stream 流深入剖析(重点详细讲解)

目录 引言 一、ArrayList 1. 概述 2. 特点 动态扩容 初始容量 扩容倍数 随机访问高效 插入和删除效率低 3. 代码示例 4. 分析 二、HashSet 1. 概述 2. 特点 唯一性 插入、删除和查找效率高 无序性 3. 代码示例 4. 分析 三、HashMap 1. 概述 2. 特点 键唯…

Golang的Goroutine(协程)与runtime

目录 Runtime 包概述 Runtime 包常用函数 1. GOMAXPROCS 2. Caller 和 Callers 3. BlockProfile 和 Stack 理解Golang的Goroutine Goroutine的基本概念 特点&#xff1a; Goroutine的创建与启动 示例代码 解释 Goroutine的调度 Gosched的作用 示例代码 输出 解…

【51单片机】3-3【定时器/计数器/中断】超声波测距模块测距

1.硬件 51最小系统超声波测距模块 2.软件 #include "reg52.h"//距离小于10cm,D5亮&#xff0c;D6灭&#xff0c;反之相反现象sbit D5 P3^7;//根据原理图&#xff08;电路图&#xff09;&#xff0c;设备变量led1指向P3组IO口的第7口 sbit D6 P3^6;//根据原理图&…