指点成金-最美分享吧

登录

第十三届蓝桥杯C++ B组 不完全题解

佚名 举报

篇首语:本文由小编为大家整理,主要介绍了第十三届蓝桥杯C++ B组 不完全题解相关的知识,希望对你有一定的参考价值。

总体上看,感觉今年的省赛题比去年的难,下面是我的个人题解,大佬勿喷

A. 九进制转十进制


这道是送分题了,2*(9**3) + 2*9 + 2 = 1478

B. 顺子日期


这道题有歧义,鬼知道012 210 321算不算,我填了4种

C. 刷题统计


先算出需要多少个星期,再算一下还要多多少天

#includeusing namespace std;typedef long long ll;int main() ll a,b,n;cin >> a >> b >> n;ll week = a * 5 + b * 2;ll m = n / week * 7;ll mm = n / week * week;int i = 0;while(mm < n) if(i <= 4) mm += a; else mm += b;++i;++m;cout << m << endl;return 0; 

D. 修剪灌木


这题换句话说就是从这个位置出发,向左走再走回来和向右走再走回来,哪个距离大

for(int i = 0; i < n; ++i) cout << max(i * 2, (n - i - 1) * 2) << endl;

E. X进制减法




这道题的难点就是X进制怎么转换成10进制
比如题目的321,从左到右分别是8/10/2进制,那么转成十进制应该是1 + 2 * (2) + 3 * (10 * 2),每一个数位都是乘上右边所有数的进制数相乘。
我的做法是贪心,不知道对不对,题目说了A>B,那肯定是进制越小最后的差越小
所以我的每一位的进制数 都是A和B这个位的数值 大的那个 加一

#includeusing namespace std;typedef long long ll;const ll mod = 1000000007;int main() int n;cin >> n;int ma, mb;cin >> ma;vector<int> aa(ma, 0);for(int i = 0; i < ma; ++i) cin >> aa[i];cin >> mb;vector<int> bb(mb, 0);for(int i = 0; i < mb; ++i) cin >> bb[i];// ======================================int mab = max(ma, mb);vector<int> a(mab, 0);vector<int> b(mab, 0);for(int i = 0; i < ma; ++i) a[ma - i - 1] = aa[i];for(int i = 0; i < mb; ++i) b[mb - i - 1] = bb[i];ll res = 0;ll p = 1;for(int i = 0; i < mab; ++i) res += (a[i] - b[i]) * p;res %= mod;p *= max(max(a[i], b[i]) + 1, 2);p %= mod;cout << res << endl;return 0; 

F. 统计子矩阵




我是直接前缀和暴力了,不出意外肯定超时,太菜了想来想去就是想不出该怎么优化。。。

G. 积木画




这个是经典DP了,有手就行,力扣有原题:https://leetcode-cn.com/problems/domino-and-tromino-tiling/

#includeusing namespace std;typedef long long ll;const ll mod = 1000000007;int main() ll n;cin >> n;vector<ll> dp(n+1);dp[0] = 1;ll p = 0;for(int i = 1; i <= n; ++i) // I 竖着摆 dp[i] += dp[i-1];dp[i] %= mod;if(i >= 2) // 两个I横着摆 dp[i] += dp[i-2];dp[i] %= mod;// 两个L型或者两个L型夹着若干个横着的I型 dp[i] += p * 2;dp[i] %= mod;if(i >= 2) p += dp[i-2];p %= mod;cout << dp[n] << endl;return 0; 

H. 扫雷




这题我的做法就是先建图,然后DFS,有一点注意的是他的数据量很大,建图的时候如果两层循环遍历,不出意外的话肯定会超时,但是可以发现r是很小的,所以我的做法是用两层的map,记录这个位置有哪些炸弹,然后枚举他附近的位置。

这题让我有点疑惑的是,如果有第二个排雷火箭,那第一次被炸掉了第二次还算不算,应该不算了吧。。

力扣上面有道很像的:https://leetcode-cn.com/problems/detonate-the-maximum-bombs/

I. 李白打酒




这题应该就是个DP,我做的时候没那么多时间了,直接丢了一个暴力就提交上去了,后面回去我补了一个DP的版本

#includeusing namespace std;typedef long long ll;const ll mod = 1000000007;int main() int n,m;cin >> n >> m;vector<vector<vector<int > > > dp(n + 1, vector<vector<int> >(m + 1,vector<int>(m + 1)));dp[0][1][1] = 1;for(int i = 0; i <= n; ++i) for(int j = 0; j <= m; ++j) for(int k = 0; k <= m; ++k) if(k > 0 && j >= 1) dp[i][j][k] += dp[i][j-1][k-1];if(k * 2 <= m && i >= 1) dp[i][j][k] += dp[i-1][j][k*2];dp[i][j][k] %= mod;cout << dp[n][m][2] << endl;return 0; 

J. 砍竹子



贪心,用一个优先队列,每次都是挑最大的下手,处理这个数的时候再向左右两边扩散,高度一样的一起干了。

发现一个规律,那些数只有最开始的时候是随机的,只要经过一次sqrt(x / 2 + 1)的处理,这个数以后都是1/6/16/30/…,一个数和他旁边的数一旦相等,以后永远都相等,所以,我对一个数进行sqrt(x / 2 + 1)处理之后,会将它重新放回优先队列,如果他隔壁的数和他原来相等,我会顺便对他隔壁的数进行sqrt(x / 2 + 1)处理,但是不会再放回优先队列。

#includeusing namespace std;typedef long long ll;struct Pll x;int idx;P(ll a, int b) : x(a), idx(b)bool operator<(const P& p) const return this->x < p.x;;int main() int n;cin >> n;vector<ll> v(n);for(int i = 0; i < n; ++i) cin >> v[i];priority_queue<P, vector<P> > pq;for(int i = 0; i < n; ++i) if(v[i] > 1) pq.push(P(v[i], i));ll res = 0;while(!pq.empty()) P p = pq.top();pq.pop();if(v[p.idx] != p.x) continue;++res;ll x = p.x;int idx = p.idx;v[idx] = sqrt(x / 2 + 1);if(v[idx] > 1) pq.push(P(v[idx], idx));int i = idx - 1;while(i >= 0 && v[i] == x) v[i--] = sqrt(x / 2 + 1);i = idx + 1;while(i < n && v[i] == x) v[i++] = sqrt(x / 2 + 1);cout << res << endl;return 0; 

总结:希望混个省一,赚回报名费

以上是关于第十三届蓝桥杯C++ B组 不完全题解的主要内容,如果未能解决你的问题,请参考以下文章