2. 4 蓝桥练习5题
今天写的几个题都挺有意思的,码量不大,主要是思维。藕还得多练QAQ
1.[P8669 蓝桥杯 2018 省 B] 乘积最大
题意:给定
请你求出最大的乘积,由于乘积可能超出整型范围,你只需输出乘积除以
注意,如果
思路:贪心+分类讨论
先排个序。如果
// AC one more times // nndbk #include <bits/stdc++.h> using namespace std; typedef long long ll; const int mod = 1e9 + 9; const int N = 2e5 + 10; ll a[N]; int main() { ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr); int n,k; cin>>n>>k; for(int i = 1;i <= n; i++) cin>>a[i]; sort(a+1,a+1+n); ll ans = 1; int l = 1,r = n; int f = 1; if(k % 2){ ans *= a[r]; if(ans < 0) f = -1; r--; k--; } while(k) { ll pre = a[l]*a[l+1]; ll suf = a[r]*a[r-1]; if(f * pre > f * suf) ans *= pre%mod,ans %= mod,l += 2; else ans *= suf%mod,ans %= mod,r -= 2; k -= 2; } cout<<ans<<"\n"; return 0; }
2.[P8625 蓝桥杯 2015 省 B] 生命之树
题意:对于一棵树,找到其点权和最大的一个连通分量(注意可以为空),输出这个连通分量的点权和。
思路:树形
// AC one more times // nndbk #include <bits/stdc++.h> using namespace std; typedef long long ll; const int mod = 1e9 + 7; const int N = 2e5 + 10; int n,a[N]; vector<int>e[N]; ll dp[N]; void dfs(int u,int fa) { //cout<<"u = "<<u<<"\n"; dp[u] = a[u]; for(auto v : e[u]) { if(v == fa)continue; dfs(v,u); dp[u] += max(dp[v],0ll); } } int main() { ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr); cin>>n; for(int i = 1;i <= n; i++) cin>>a[i]; for(int i = 1;i < n; i++) { int u,v; cin>>u>>v; e[u].push_back(v); e[v].push_back(u); } dfs(1,0); ll ans = 0; for(int i = 1;i <= n; i++) { ans = max(ans,dp[i]); } cout<<ans<<"\n"; return 0; }
3.[P8782 蓝桥杯 2022 省 B] X 进制减法
题意:两个
思路:
通式就是:
那么对于
好的了解了以上,我们来考虑本题。本题是要求差值最小。因为题目保证了
// AC one more times // nndbk #include <bits/stdc++.h> using namespace std; typedef long long ll; const int mod = 1e9 + 7; const int N = 2e5 + 10; ll n,la,lb,a[N],b[N],c[N],d[N]; int main() { ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr); cin>>n; cin>>la; for(int i = la;i >= 1; i--) cin>>a[i]; cin>>lb; for(int i = lb;i >= 1; i--) cin>>b[i]; for(int i = 1;i <= max(la,lb); i++) { c[i] = max(a[i],b[i])+1; if(c[i]<2)c[i] = 2; } d[1] = 1; for(int i = 2;i <= max(la,lb);i++) d[i] = (d[i-1]*c[i-1])%mod; ll t1 = 0,t2 = 0; for(int i = 1;i <= la;i++) t1 += (a[i]*d[i])%mod,t1 %= mod; for(int i = 1;i <= lb;i++) t2 += (b[i]*d[i])%mod,t2 %= mod; cout<<(t1-t2+mod)%mod<<"\n"; return 0; }
4.[P8683 蓝桥杯 2019 省 B] 后缀表达式
题意:给定
请你输出这个最大的结果。
例如使用 1 2 3 + -
,则 2 3 + 1 -
这个后缀表达式结果是
思路:这题很有意思,想了很久。后缀表达式是可以加括号滴。
比如
0 2 1 2 3
答案应该是4。因为3-(1-2) = 4。如果直接贪心的话求出来是3-2-1 = 0。
那么怎么办哩?
我们先考虑简单的,如果全是加号,那么答案一定是直接全部加起来就行了。
那么如果有减号存在呢?
一个负数通过加括号和减号来变成正数
对于负数
我们发现了什么?是不是只要有一个负号,我们就可以把若干个负数变成正数啦。我们考虑多加上大数,减去小数。我们考虑把max放首相,min放后面,构成以下表达式。
其他数:
- 正数 + :放在②
- 负数 - :放在②
- 正数 - : 放在①
- 负数 + :放在①
我们发现无论怎么放都是正数,完美解决。
// AC one more times // nndbk #include <bits/stdc++.h> using namespace std; typedef long long ll; const int mod = 1e9 + 7; const int N = 2e5 + 10; ll a[N]; int main() { ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr); int n,m; cin>>n>>m; int k = n+m+1; for(int i = 1;i <= k; i++) cin>>a[i]; sort(a+1,a+1+k); ll ans = 0; if(m==0) { for(int i = 1;i <= k; i++) ans += a[i]; } else{ ans = a[k]-a[1]; for(int i = 2;i < k; i++) ans += abs(a[i]); } cout<<ans<<"\n"; return 0; }
5.[P8783 蓝桥杯 2022 省 B] 统计子矩阵
题意:给定一个
思路:看见这个第一反应就是二维前缀和+枚举。枚举4维肯定是不行的,我就想枚举左上角和左下角的x再二分y。结果。。。还是TLE了hh。
// AC one more times // nndbk #include <bits/stdc++.h> using namespace std; typedef long long ll; #define int long long const int mod = 1e9 + 7; const int N = 5e2 + 10; ll n,m,k; ll a[N][N],s[N][N]; bool judge(int x1,int y1,int x2,int y2) { ll sum = s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1]; return sum <= k; } signed main() { ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr); cin>>n>>m>>k; 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++) s[i][j] = s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j]; ll ans = 0; for(int i = 1;i <= n; i++) { for(int j = 1;j <= m; j++) { int last = m; for(int k = i;k <= n; k++) { int x1 = i,y1 = j; int x2 = k,y2; int l = j, r = last; while(l<=r) { int mid = (l+r)>>1; if(judge(x1,y1,x2,mid))l = mid+1; else r = mid-1; } y2 = l-1; if(y2<y1)break; last = y2; ans += (y2-y1+1); } } } cout<<ans<<"\n"; return 0; }
以上代码只有80分。那么得把log优化掉怎么办哩。我们考虑双指针。
枚举
// AC one more times // nndbk #include <bits/stdc++.h> using namespace std; typedef long long ll; #define int long long const int mod = 1e9 + 7; const int N = 5e2 + 10; ll n,m,k; ll a[N][N],s[N][N]; signed main() { ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr); cin>>n>>m>>k; 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++) s[i][j] = s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j]; ll ans = 0; for(int i = 1;i <= n; i++)//x1 { for(int j = i;j <= n; j++)//x2 { for(int l = 1,r = 1;r <= m; r++)//y1,y2 { while(l <= r &&s[j][r] - s[i - 1][r] - s[j][l - 1] + s[i - 1][l - 1] > k)l++; ans += r-l+1; } } } cout<<ans<<"\n"; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix