2022年第十三届蓝桥杯大赛软件类决赛C/C++大学B组真题

发布时间 2023-04-01 15:04:06作者: Liang2003

2022年第十三届蓝桥杯大赛软件类决赛C/C++大学B组真题

卡牌

const int N=2e5+10;
pii a[N];
int sum;
int b[N];
int n,m;
void solve() 
{
	int mx=1e18,ans=0;
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>a[i].first,a[i].second=i;
	for(int i=1;i<=n;i++) cin>>b[i];
	for(int i=1;i<=n;i++) mx=min(mx,a[i].first+b[i]);
	sort(a+1,a+1+n);
    int i;
    a[n+1]={mx,n+1};
	for(i=1;i<=n+1;i++) 
	{
		if(a[i].first>mx) {ans=mx; break;}
		if((i-1)*a[i].first-sum<=m)
		{
			ans=a[i].first;
		}  
		else {ans=min(mx,(sum+m)/(i-1));break;}
		sum+=a[i].first;
	}

	cout<<ans<<endl;
}

最大数字

int a,b;
int p[20],cnt;
int e[20];
int ans,n;
void init() 
{
	e[0]=1;
	for(int i=1;i<20;i++) e[i]=e[i-1]*10;
}

void dfs(int pos,int num,int a,int b) 
{
	if(!pos) 
	{
		ans=max(ans,num);
		return;
	}
	//if(num*e[pos-1]<ans) return ;//这个剪枝是不对的
	int flag=0;
	for(int i=9;i>p[pos];i--) 
	{
		int ca=i-p[pos],cb=p[pos]-i+10;
		if(a>=ca) dfs(pos-1,num*10+i,a-ca,b),flag=1;
		if(b>=cb) dfs(pos-1,num*10+i,a,b-cb),flag=1;
		if(flag) break;
	}
	dfs(pos-1,num*10+p[pos],a,b);
}

出差

最短路简单题

void dijk()
{
	memset(dis,0x3f,sizeof(dis));
	dis[1]=0;
	priority_queue<pii> q;
	q.push({dis[1],1});
	while(q.size()) 
	{
		pii tmp=q.top();
		q.pop();
		int u=tmp.second;
		if(vis[u]) continue;
		vis[u]=true;
		for(int i=h[u];i!=-1;i=ne[i]) 
		{
			int j=e[i];
			if(dis[j]>dis[u]+w[i]+val[j]) 
			{
				dis[j]=dis[u]+w[i]+val[j];
				if(!vis[j]) 
				{
					q.push({-dis[j],j});
				}
			}
		}
	}
}

void solve() 
{
	cin>>n>>m;
	memset(h,-1,sizeof(h));
	for(int i=1;i<=n;i++) cin>>val[i];
	for(int i=1;i<=m;i++) 
	{
		int a,b,c;
		cin>>a>>b>>c;
		add(a,b,c);
		add(b,a,c);
	}
	if(n==1) {cout<<0<<endl;return;}//这个很重要
	dijk();
	cout<<dis[n]-val[n]<<endl;
}

费用报销

按照日期编号先排个序,瞎弄一波就可以了

int day[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int get(int a,int b) //编号
{
	return day[a-1]+b;
}
int n,m,K;
pii f[5010];

struct node 
{
	int a,b,val,num;
	bool operator < (const node &d)const
	{
		return num<d.num;
	}
}p[1010];

void solve() 
{
	for(int i=1;i<=12;i++) day[i]+=day[i-1];
	cin>>n>>m>>K;
	for(int i=1;i<=n;i++) cin>>p[i].a>>p[i].b>>p[i].val,p[i].num=get(p[i].a,p[i].b);
	sort(p+1,p+1+n);
	//for(int i=1;i<=n;i++) cout<<p[i].a<<" "<<p[i].b<<" "<<p[i].num<<endl;
	//f[i][j][k]表示前i张票 组成的金额为j,日期最近的一张票编号为k
	//当前票据编号为x,金额为y 状态转移:f[i][j+x][y]|=f[i-1][j][y-K+1及以下]
	for(int i=1;i<=m;i++) f[i]={0,-1};
	f[0]={1,-1000};
	for(int i=1;i<=n;i++) 
	{	
		int val=p[i].val,num=p[i].num;
		for(int j=0;j+val<=m;j++) 
		{
			if(f[j].first==0) continue;
			if(f[j+val].second==-1&&f[j].second+K<=num)
			{	
				f[j+val].first=1;
				f[j+val].second=num;
			}
		}
	}
	for(int i=m;i>=0;i--) if(f[i].first) {cout<<i;return;}
}

故障

全概率加贝叶斯公式 ,但要注意的是 精度问题,long double,精度误差真的要开小一点,考试时什么都考虑时最稳的

#include<bits/stdc++.h>
#include<iomanip>
using namespace std;
#define int long long
#define pii pair<int,int> 
#define inf 0x3f3f3f3f
const int N=110;
const double eps=1e-12;
int n,m,k;
long double p[N][N];

struct node 
{
	int num;
	long double p;
	inline bool operator <(const node a)const
	{	
		if(fabs(p-a.p)<eps) 
		{
			return num<a.num;
		}
		return p>a.p;
	}
}ans[N];

void solve() 
{
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>p[i][0];
	for(int i=1;i<=n;i++) 
	{
		for(int j=1;j<=m;j++) 
		{
			cin>>p[i][j];
			p[i][j]=100-p[i][j];
		}
	}
	cin>>k;
	while(k--) 
	{
		int x;
		cin>>x;
		for(int i=1;i<=n;i++) p[i][x]=100-p[i][x];
	}
	long double sum=0;
	for(int i=1;i<=n;i++) 
	{	
		ans[i].num=i;
		ans[i].p=1;
		for(int j=0;j<=m;j++) 
		{
			ans[i].p=ans[i].p*p[i][j]/100.0;
		}
		sum+=ans[i].p;
	}
	//cout<<sum<<endl;
	sort(ans+1,ans+1+n);
	for(int i=1;i<=n;i++) 
	{
		cout<<ans[i].num<<" ";
		if(fabs(sum)<eps) cout<<"0.00"<<endl;
		else cout<<fixed<<setprecision(2)<<ans[i].p/sum*100<<endl;
	}
}

signed main()
{
 	ios::sync_with_stdio(false);
    cin.tie(0);
 	cout.tie(0);
 	int t=1;
 	//cin>>t;
 	while(t--) solve();
    return 0;
}

齿轮

题目的数据范围是关键,半径和转速都限定在2e5内

bool vis[N];
int a[N];
int n,m;
void solve() 
{
	cin>>n>>m;
	for(int i=1;i<=n;i++) 
	{
		int x;
		cin>>x;
		a[x]++;
	}
	for(int i=1;i<N;i++)
	{
		if(!a[i]) continue;
		if(a[i]>1) vis[1]=1;
		for(int j=2*i;j<N;j+=i)
		{
			if(a[j]) vis[j/i]=1;
		}
	}
	if(n==1) vis[1]=1;
	while(m--) 
	{
		int x;
		cin>>x;
		if(vis[x]) cout<<"YES\n";
		else cout<<"NO\n";
	}
}

机房

真的惨烈,倍增和tarjan都用过了,还是有三个点超时,看了一个多小时中间还把齿轮那题做了,最后才发现endl没有define

const int N=2e5+10;
const double eps=1e-12;
int n,m,k;
int h[N],e[N*2],ne[N*2],idx;
int val[N],dis[N];
int f[N][22],dep[N];
int q[N],hh,tt;
void add(int a,int b) 
{
	e[idx]=b;
	ne[idx]=h[a];
	h[a]=idx++;
}

int lca(int a,int b) 
{
	if(dep[a]<dep[b]) swap(a,b);
	for(int k=20;k>=0;k--) 
	{
		if(dep[f[a][k]]>=dep[b]) a=f[a][k];
	}
	if(a==b) return a;
	for(int k=20;k>=0;k--)
	{
		if(f[a][k]!=f[b][k]) a=f[a][k],b=f[b][k];
	}
	return f[a][0];
}

void bfs()
{	
	fill(dis,dis+n+10,inf);
	q[++tt]=1;
	dis[1]=val[1];
	dep[1]=1;
	f[1][0]=1;
	while(hh<tt)
	{
		int u=q[++hh];
		for(int i=h[u];i!=-1;i=ne[i]) 
		{
			int j=e[i];
			if(dep[j]) continue;
			dis[j]=dis[u]+val[j];
			q[++tt]=j;
			f[j][0]=u;
			dep[j]=dep[u]+1;
			for(int k=1;k<=20;k++) f[j][k]=f[f[j][k-1]][k-1];
		}
	}
	//for(int i=1;i<=n;i++) cout<<dis[i]<<" ";
	//cout<<endl;
}

void solve() 
{	
	cin>>n>>m;//
	fill(h,h+n+10,-1);
	for(int i=1;i<n;i++) 
	{
		int a,b;
		cin>>a>>b;
		add(a,b);
		add(b,a);
		val[a]++,val[b]++;
	}
	bfs();
	map<pii,int> mp;
	while(m--) 
	{
		int a,b;
		cin>>a>>b;
		if(mp.count({a,b})) cout<<mp[{a,b}]<<endl;
		else 
		{	
			int k=lca(a,b);
			mp[{a,b}]=mp[{b,a}]=dis[a]+dis[b]-2*dis[k]+val[k];
			cout<<mp[{a,b}]<<endl;
		}
	}
}

搬砖

最优解是排序后的一个子序列,要找排序条件。
显然不会,看看别人的题解。

struct node
{
	int w,v;
	bool operator <(const node d)const 
	{		
		return w+v<d.w+d.v;
	}
}a[N];

int f[N*40];

void solve() 
{
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i].w>>a[i].v;
	sort(a+1,a+1+n);
	for(int i=1;i<=n;i++) 
	{
		int w=a[i].w,v=a[i].v;
		//cout<<w<<" "<<v<<endl;
		for(int j=v;j>=0;j--)
		{
			f[j+w]=max(f[j+w],f[j]+v);
		}
	}
	int ans=0;
	for(int i=0;i<N*20;i++) ans=max(ans,f[i]);
	cout<<ans<<endl;
}

2023.4.1,距离蓝桥杯还有六天