蓝桥杯2023C++A组
(此文为简单的赛后记录,代码没有经过修改不保证正确
A 幸运数
将数字分为前一半和后一半dp方案数再乘起来
B 有奖问答
dpi,j表示第i轮 得分为10j的情况
注意一下在任意轮都可以结束并且j=10是不能转移的
C 平方差
当且仅当 \(x = 4^a * (2b+1) (a,b>=0)\) 统计
时间复杂度:\(O(log R)\)
D 更小的数
一个重要的观察:子串反转要么在首位和末尾比出大小,要么首位和末尾相等
做法一:\(dp_{i,j}\) 表示反转 j 到 j + i - 1 的子串是否更小 \(O(n^2)\)
做法而:分治,将左(右)区间每个位置看成一个二维的点(x,y),x是当前位置是什么数字,y是当前位置之前(之后)是什么数字,枚举右区间,对左区间统计二维前缀和就可以统计跨越左右区间贡献的答案
时间复杂度:\(O(n D^2 log n)\) D 是字符集大小,\(|D|=10\)
E 颜色平衡树
不会wuwu
F 买瓜
天天看华强结果一点思路都没有,,,
G 网络稳定性
说法很多
求最大生成树
之后就是一个求最小边的问题
考场写了倍增
\(O(N log \ M + (Q+N) log \ N)\)
#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
#define inf 1e7
using namespace std;
const int N = 200010, M = 300010;
int n,m,q,f[N][19],g[N][19],dep[N],fa[N],o,hd[N],vis[N];
struct edge{int u,v,w;}e[M];
struct Edge{int v,nt,w;}E[N<<1];
bool cmp(const edge&A,const edge&B){return A.w>B.w;}
void adde(int u,int v,int w){
E[o]=(Edge){v,hd[u],w};hd[u]=o++;
E[o]=(Edge){u,hd[v],w};hd[v]=o++;
}
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
void dfs(int u,int F){
vis[u]=1;
for(int i=1;(1<<i)<=dep[u];++i){
f[u][i] = f[f[u][i-1]][i-1];
g[u][i] = min(g[f[u][i-1]][i-1] , g[u][i-1]); //!
}
for(int i=hd[u];~i;i=E[i].nt){
int v=E[i].v, w=E[i].w;
if(v==F)continue;
dep[v] = dep[u] + 1;
f[v][0] = u;
g[v][0] = w;
dfs(v,u);
}
}
int solve(int u,int v){
int re=inf;
if(dep[u]<dep[v])swap(u,v);
int du=dep[u]-dep[v];
for(int i=18;~i;--i)if((du>>i)&1)re=min(re,g[u][i]),u=f[u][i];
if(u==v)return re;
for(int i=18;~i;--i){
if(f[u][i]!=f[v][i]){
re = min(re, g[u][i]);
re = min(re, g[v][i]);
u = f[u][i], v=f[v][i];
}
}
re = min(re, g[u][0]);
re = min(re, g[v][0]);
return re;
}
int main(){
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=m;++i){
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
}
//生成树
sort(e+1,e+m+1,cmp);
for(int i=1;i<=n;++i)fa[i]=i,hd[i]=-1;
for(int i=1;i<=m;++i){
int fx = find(e[i].u);
int fy = find(e[i].v);
if(fx == fy)continue;
fa[fy]=fx;
adde(e[i].u,e[i].v,e[i].w);
}
//倍增求答案
for(int i=1;i<=n;++i)if(!vis[i])dfs(i,0);
for(int i=1;i<=q;++i){
int u,v;
scanf("%d%d",&u,&v);
if(find(u)!=find(v)){puts("-1");continue;}
cout<<solve(u,v)<<endl;
}
return 0;
}
H 异或和之和
按位统计答案,统计异为0 和 1的前缀个数相乘即可
I 像素放置
我想写插头dp
没有写出来,最后二十分钟来调暴力也没调出来,很可惜50%
吸取教训:像这种题肯定是先写暴力的,就算要写正解也需要暴力来对拍
\(O(NM4^M)\) 不知道能不能过。。。等题解
J 翻转硬币
不会做orz