蓝桥杯C/C++真题
时间: 2025-04-16 08:41:26 浏览: 38
### 蓝桥杯 C/C++ 历年真题及解析
#### 2024 年蓝桥杯 C/C++ 组部分真题解析
对于零食采购问题,采用的是 LCA 算法来解决每次查询消耗 logN 的树上差分完整代码[^2]:
```cpp
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;
vector<int> G[MAXN];
int dep[MAXN], fa[MAXN][20], dfn[MAXN], siz[MAXN], top[MAXN], son[MAXN], dis[MAXN];
bool vis[MAXN];
void dfs1(int u, int f, int d) {
dep[u] = d;
fa[u][0] = f;
siz[u] = 1;
for (auto v : G[u]) {
if (v == f) continue;
dis[v] = dis[u] + 1;
dfs1(v, u, d + 1);
siz[u] += siz[v];
if (siz[v] > siz[son[u]]) son[u] = v;
}
}
void dfs2(int u, int t) {
dfn[u] = ++dfn[0];
top[u] = t;
if (!son[u]) return;
dfs2(son[u], t);
for (auto v : G[u])
if (v != fa[u][0] && v != son[u])
dfs2(v, v);
}
inline int lca(int x, int y) {
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]])
swap(x, y);
x = fa[top[x]][0];
}
return dep[x] < dep[y] ? x : y;
}
```
训练士兵题目涉及到较为复杂的逻辑处理,具体实现如下所示:
```cpp
struct node {
int id, a, b;
} p[maxn];
bool cmp(node x, node y) {
return x.a * y.b < y.a * x.b || (x.a * y.b == y.a * x.b && x.id < y.id);
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) scanf("%d%d", &p[i].a, &p[i].b), p[i].id = i;
sort(p + 1, p + 1 + n, cmp);
long long ans = 0;
for (int i = 1; i <= n; i++)
ans = ((ans % mod) + (((((long long)p[i].a * p[i].b) % mod)) *
inv(i))) %
mod;
cout << ans << endl;
return 0;
}
```
成绩统计则利用了二分算法来进行优化,从而降低了时间复杂度。以下是具体的代码实现:
```cpp
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll read(){
ll s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while('0'<=ch&&ch<='9') s=s*10+ch-'0',ch=getchar();
return w*s;
}
const int N=1e6+7,M=N<<1;
int h[N],to[M],ne[M],idx,n,m,S,T,d[N],q[N],cur[N];
double mid,f[N];
bool st[N];
void add(int a,int b){
ne[++idx]=h[a],to[h[a]=idx]=b;
ne[++idx]=h[b],to[h[b]=idx]=a;
}
bool bfs(double lim){
for(int i=S;i<=T;++i)d[i]=-1,cur[i]=h[i];
d[q[l=r=1]=S]=0;
while(l<=r){
int now=q[l++];
for(int i=h[now];~i;i=ne[i]){
if(d[to[i]]==-1&&f[to[i]]>=lim){
q[++r]=to[i];
cur[to[i]]=h[to[i]];
d[to[i]]=d[now]+1;
if(to[i]==T)return true;
}
}
}
return false;
}
int dinic(int now,double lim,int flow){
if(now==T||flow==0)return flow;
int rest=flow,k;
for(int &i=cur[now];~i;i=ne[i]){
if(f[to[i]]>=lim&&d[to[i]]==d[now]+1&&(k=dinic(to[i],lim,min(rest,(int)f[to[i]]))){
f[from[i]]+=k,f[to[i]]-=k,rest-=k;
if(!rest)break;
}
}
if(flow==rest)d[now]=-1;
return flow-rest;
}
signed main(){
memset(h,-1,sizeof h);
n=read(),m=read(),S=n+m+1,T=n+m+2;
for(int i=1;i<=n;++i)
add(S,i),scanf("%lf",&f[i]);
for(int i=1;i<=m;++i)
add(n+i,T),scanf("%lf",&f[n+i]),f[n+i]*=-1;
for(int i=1,x,y;i<=read();++i)x=read(),y=read()+n,add(x,y);
double l=0,r=1,mid=(l+r)/2;
while(r-l>eps){
mid=(l+r)/2;
bool flag=false;
for(int i=1;i<=n;++i)flag|=dinic(S,mid,inf)>0;
flag?l=mid:r=mid;
}
printf("%.8lf\n",-l);
}
```
#### 过往年度的真题分析
针对过往年度的比赛,在某些情况下会使用暴力枚举的方法解决问题。例如在寻找特定条件下的数列时可以采取以下方式[^3]:
```cpp
void solve(){
init();
int ans,pri;
for(int i = 2;i <= 400;i++){
for(int j = 1;j <= prime[0];j++){
ans = search(prime[j],i);
if(ans!=-1){
pri = prime[j];
break;
}
}
if(ans!=-1) break;
}
cout << ans << endl;
}
```
此外还有其他类型的题目,比如计算组合数量等问题也经常出现在比赛中[^4]。
阅读全文
相关推荐


















