Problem A 空间

计组基础题:256MB=256 * 2^20 * 8 位
所以存放32位元素可以存放 256 * 1024 * 1024 * 8 / 32
ans: 67108864
送分题
Problem B 卡片

题目就是说0—9一共9种卡片,如果,每个3张可以排到10,那如果每个2021张可以排到多少?
我的思路:
第一遍做这个题时写了个3182,后来检查时又仔细读了一遍题发现不对,最后应该输出3181,差点儿错了,,,

code:
#include<bits/stdc++.h> using namespace std; int num[10]; int del(int n) {
while(n){ int index=n%10; if(num[index]==0)return 0; else num[index]--; n/=10; }
return 1; } int main() { for(int i=0;i<=9;i++){ num[i]=2021; } int n=1; while(1)
{ int ff=del(n); if(ff==0)break; else n++; } printf("%d",n-1); return 0; }
ans:3181

Problem C直线

我的思路:
这题我错了,
我用的set<pair<double,double> >
line_set;存放k与b,最后输出20+21+line_set.size(),然后,,,然后就错了,,,double精度导致错误;

error code:
#include<bits/stdc++.h> using namespace std; set<pair<double,double> > line_set
; int main() { int x1,y1,x2,y2; for(x1=0;x1<20;x1++){ for(y1=0;y1<21;y1++){ for(
x2=0;x2<20;x2++){ for(y2=0;y2<21;y2++){ if(x1!=x2&&y1!=y2){ double k=(y2-y1)*1.0
/(x2-x1); double b=y2-k*x2; pair<double ,double > newline; newline.first=k;
newline.second=b; line_set.insert(newline); } } } } } printf("%d",line_set.size(
)+20+21); return 0; }
这样算出来是47753(error ans),知乎上有人说是40257,哎,蓝瘦~
贴一下正确解:
#include<bits/stdc++.h> using namespace std; set<pair<double,double> > line_set
; int main() { int x1,y1,x2,y2; for(x1=0;x1<20;x1++){ for(y1=0;y1<21;y1++){ for(
x2=0;x2<20;x2++){ for(y2=0;y2<21;y2++){ if(x1!=x2&&y1!=y2){ double k=(y2-y1)*1.0
/(x2-x1); double b=(y2*(x2-x1)-(y2-y1)*x2)*1.0/(x2-x1); //重点!这么写可以规避掉double炸精度问题
pair<double ,double> newline; newline.first=k; newline.second=b; line_set.
insert(newline); } } } } } printf("%d",line_set.size()+20+21); return 0; }
//40257
Problem D货物摆放

这个题没有办法,暴力吧,纯暴力还不行,必须优化!
我的思路:
由于要拆解成因子,拆解的三个因子(设为a,b,c),把a,b,c放到一个集合里s;
始终要a<=b<=c(不然超时!)
如果s.size()==1,ans+=1;//abc三者相等,为一种情况
如果s.size()==2,ans+=3;//abc三个有两个相等,则独立的哪个有三种放法
如果s.size()==3,ans+=6;//abc互不相等,全排列3 * 2 *1种

循环一定要两层,不要三层,必须使用sqrt降低复杂度

code:
#include<bits/stdc++.h> using namespace std; typedef long long ll; int main() {
ll n=2021041820210418; ll en1=sqrt(n); ll ans=0; for(ll a=1;a<=en1;a++){ if(n%a
==0){ ll nn=n/a; ll en2=sqrt(nn); for(ll b=1;b<=en2;b++){ if(nn%b==0){ ll c=nn/b
; if(c>=b&&b>=a){ set<int> s; s.insert(a); s.insert(b); s.insert(c); if(s.size()
==1)ans++; else if(s.size()==2)ans+=3; else if(s.size()==3)ans+=6; } } } } }
printf("%lld",ans); return 0; }
ans:2430
Problem E路径

我的思路:
dijkstra即可,然而呢,我写的dijkstra调试了半天也不对,气急败坏之下又用的Floyd,三层for循环,等了10秒左右总算是跑出来了,,,
code:
#include<bits/stdc++.h> using namespace std; typedef long long ll; #define INF
999999999 int gcd(int a,int b){ if(b==0)return a; else return gcd(b,a%b); } int
M[2022][2022]; int main(){ for(int i=1;i<=2021;i++){ for(int j=1;j<=2021;j++){
if(i==j)M[i][j]=M[j][i]=0; else if(abs(i-j)>21)M[i][j]=M[j][i]=INF; else M[i][j]
=M[j][i]=i*j/gcd(i,j); } } for(int i=1;i<=2021;i++){ for(int j=i+1;j<=2021;j++){
for(int k=i;k<=j;k++){ if(M[i][k]!=INF&&M[k][j]!=INF&&(M[i][j]>M[i][k]+M[k][j]))
{ M[i][j]=M[j][i]=M[i][k]+M[k][j]; } } } } printf("%lld",M[1][2021]); return 0;
}
ans:10266837

Problem F时间显示

题干说给出一个毫秒数,输出对应的hh:mm:ss
我的思路:
签到题
input_case1:
46800999
output_case1:
13:00:00
input_case2:
1618708103123
output_case2:
01:08:23
code:
#include<bits/stdc++.h> using namespace std; typedef long long ll; int main() {
ll n; scanf("%lld",&n); n/=1000; n%=(24*60*60); int ss=n%60; n/=60; int mm=n%60
; n/=60; int hh=n%60; n/=60; printf("%02d:%02d:%02d",hh,mm,ss); return 0; }
Problem G砝码称重

我的思路:

哎,万万没想到,第二个编程题直接来个dp,蓝桥杯啊,你变了啊,做往年的省赛b组题基本没遇到过dp,去年考了dp也只是在填空里考了,今年直接第二道编程考dp,哎,菜是原罪!
看了半天没思路,又看了看测试样例范围 50%的样例在1<=n<=15,果断dfs深搜骗分,,,
input_case:
3
1 4 6
output_case:
10
code:
#include<bits/stdc++.h> using namespace std; int n; int w[102]; int flag[102];
set<int> ans; int ff=0; void dfs(int sum1,int sum2){ if(sum1<sum2)return ; else{
if(sum1>sum2){ ans.insert(sum1-sum2); } } for(int i=1;i<=n;i++){ if(!flag[i]){
flag[i]=1; dfs(sum1+w[i],sum2); dfs(sum1,sum2+w[i]); flag[i]=0; } } } int main()
{ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&w[i]); } dfs(0,0); printf(
"%d",ans.size()); return 0; }
贴一下正确解:
#include<bits/stdc++.h> using namespace std; typedef long long ll; int dp[102][
100002]; int main() { int n; scanf("%d",&n); int w[n+1]; ll sum=0; for(int i=1;i
<=n;i++){ scanf("%d",&w[i]); sum+=w[i]; } for(int i=1;i<=n;i++){ for(int j=1;j<=
sum;j++){ dp[i][j]=dp[i-1][j]; if(dp[i][j]==0){ if(w[i]>j)dp[i][j]=dp[i-1][w[i]-
j]; if(w[i]==j)dp[i][j]=1; if(w[i]<j)dp[i][j]=dp[i-1][j-w[i]]; } } } ll ans=0;
for(int i=1;i<=sum;i++){ if(dp[n][i])ans++; } printf("%lld",ans); return 0; }
Problem H杨辉三角

我的思路:
没思路,,暴力骗分,,
组合数学问题
input_case:
6
output_case:
13
code:
#include<bits/stdc++.h> using namespace std; int M[3001][3001]; int main(){ int
n; scanf("%d",&n); for(int i=1;i<=n+1&&i<=3000;i++){ M[i][i]=1; M[i][1]=1; }
for(int i=3;i<=n+1&&i<=3000;i++){ for(int j=2;j<i;j++){ M[i][j]=M[i-1][j]+M[i-1]
[j-1]; } } int num=1; for(int i=1;i<=n+1&&i<=3000;i++){ for(int j=1;j<=i;j++){
if(M[i][j]==n){ printf("%d",num); return 0; }else{ num++; } } } return 0; }
Problem I双向排序

我的思路:
sort骗分,

刚开始以为用sort连30%的测试点都过不了(毕竟快排的最坏时间复杂度是平方阶的!),后来看了一下别人博客了解到,sort还是很牛的,毕竟是c++封装好的排序函数,记得之前学快排的时候,快排有好几种优化方案,什么三点取中法,等等,c++里面的sort是优化到极致的快排,很好用;
! (~ _ ~;)
n=4000,m=4000是不超时的,sort至少可以骗50%的分数。
input_case:
3 3
0 3
1 2
0 2
output_case:
3 1 2

code:
#include<bits/stdc++.h> using namespace std; bool cmp1(int a,int b)//升序 {
return a<b; } bool cmp2(int a,int b)//降序 { return a>b; } int main(){ int n,m;
scanf("%d %d",&n,&m); int a[n+1]; for(int i=1;i<=n;i++){ a[i]=i; } int op,index;
for(int i=0;i<m;i++){ scanf("%d %d",&op,&index); if(op==0){ sort(a+1,a+index+1,
cmp2); }else{ sort(a+index,a+n+1,cmp1); } } for(int i=1;i<=n;i++){ printf("%d",a
[i]); if(i<n)printf(" "); } return 0; }
Problem J括号序列

我的思路:
状压dp,蓝桥杯是真的变了,,,
又是dfs写的,骗分,,,
input_case:
((()
oupput_case:
5
code:
#include<bits/stdc++.h> using namespace std; string s; set<string> e; int
addNum; char c; bool isok() { stack<char> sta; for(int i=0;i<s.size();i++){ if(s
[i]=='('){ sta.push(s[i]); }else{ if(sta.empty()||sta.top()!='(')return false;
else sta.pop(); } } if(sta.empty())return true; else return false; } void dfs(
int depth){ if(depth==addNum){ if(isok()){ e.insert(s); } }else{ for(int i=0;i<s
.size();i++){ s.insert(s.begin()+i,c); dfs(depth+1); s.erase(s.begin()+i,s.begin
()+i+1); } } } int main() { cin>>s; int left=0,right=0; for(int i=0;i<s.size();i
++){ if(s[i]=='(')left++; else right++; } if(left==right){ printf("0"); return 0
; }else{ if(left>right)c=')'; else c='('; addNum=abs(left-right); dfs(0); printf
("%d",e.size()); } return 0; }
总结:
填空对了4道,编程题只有第一个保证ac,其它4个均是dfs,,,暴力,,,骗分,,,

第一次参加蓝桥杯就突然难了,哎,菜是原罪啊!蓝桥杯是真的变了,加入了蝉联出题就硬气了,这几年来蓝桥杯也一直为人诟病,今年突然难了其实也是好事吧,希望蓝桥杯发展的越来越好吧。

技术
下载桌面版
GitHub
百度网盘(提取码:draw)
Gitee
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:[email protected]
QQ群:766591547
关注微信