2022年第十三届蓝桥杯大赛软件类决赛C/C++大学B组真题
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;
}