2025.4.30
P8655 [蓝桥杯 2017 国 B] 发现环
题目描述
小明的实验室有 $N$ 台电脑,编号 $1 \sim N$。原本这 $N$ 台电脑之间有 $N-1$ 条数据链接相连,恰好构成一个树形网络。在树形网络上,任意两台电脑之间有唯一的路径相连。
不过在最近一次维护网络时,管理员误操作使得某两台电脑之间增加了一条数据链接,于是网络中出现了环路。环路上的电脑由于两两之间不再是只有一条路径,使得这些电脑上的数据传输出现了 BUG。
为了恢复正常传输。小明需要找到所有在环路上的电脑,你能帮助他吗?
输入格式
第一行包含一个整数 $N$。
以下 $N$ 行每行两个整数 $a$ 和 $b$,表示 $a$ 和 $b$ 之间有一条数据链接相连。
输入保证合法。
输出格式
按从小到大的顺序输出在环路上的电脑的编号,中间由一个空格分隔。
输入输出样例 #1
输入 #1
5
1 2
3 1
2 4
2 5
5 3
输出 #1
1 2 3 5
说明/提示
对于 $30%$ 的数据,$1 \le N \le 1000$。
对于 $100%$ 的数据,$1 \le N \le 10^5$,$1 \le a,b \le N$。
时限 1 秒, 256M。蓝桥杯 2017 年第八届国赛
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int d[N];
int h[N],ne[N],to[N],idx=0;
void add(int a,int b){
to[++idx]=b;
ne[idx]=h[a];
h[a]=idx;
}
int main(){
int n;
cin>>n;
unordered_set<int> s;
memset(h,-1,sizeof h);
for(int i=1;i<=n;i++){
int u,v;
cin>>u>>v;
d[u]++,d[v]++;
add(u,v);
add(v,u);
}
queue<int> q;
for(int i=1;i<=n;i++)
if(d[i]==1) q.push(i),s.insert(i);
while(q.size()){
int u=q.front();
q.pop();
for(int i=h[u];~i;i=ne[i]){
int v=to[i];
if(--d[v]==1){
q.push(v);
s.insert(v);
}
}
}
for(int i=1;i<=n;i++)
if(s.find(i)==s.end()) cout<<i<<' ';
return 0;
}
P8669 [蓝桥杯 2018 省 B] 乘积最大
题目描述
给定 $N$ 个整数 $A_1, A_2,\cdots, A_N$。请你从中选出 $K$ 个数,使其乘积最大。
请你求出最大的乘积,由于乘积可能超出整型范围,你只需输出乘积除以 $1000000009$(即 $10^9+9$)的余数。
注意,如果 $X<0$, 我们定义 $X$ 除以 $1000000009$ 的余数是 $0-((0-x)\bmod 1000000009)$。
输入格式
第一行包含两个整数 $N$ 和 $K$。
以下 $N$ 行每行一个整数 $A_i$。
输出格式
一个整数,表示答案。
输入输出样例 #1
输入 #1
5 3
-100000
-10000
2
100000
10000
输出 #1
999100009
输入输出样例 #2
输入 #2
5 3
-100000
-100000
-2
-100000
-100000
输出 #2
-999999829
说明/提示
对于 $40%$ 的数据,$1\le K\le N\le 100$。
对于 $60%$ 的数据,$1\le K \le 1000$。
对于 $100%$ 的数据,$1\le K\le N\le 105$,$-105\le A_i\le 10^5$。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10,mod=1e9+9;
int a[N];
int n,k;
signed main(){
cin>>n>>k;
for(int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+n+1);
int ans=1;
int l=1,r=n;
if(k%2) ans*=a[n],r=n-1;
k/=2;
int f=ans<0? -1:1;
for(int i=1;i<=k;i++){
if(a[l]*a[l+1]*f>a[r]*a[r-1]*f) ans=ans%mod*a[l]%mod*a[l+1]%mod,l+=2;
else ans=ans%mod*a[r]%mod*a[r-1]%mod,r-=2;
}
cout<<ans%mod<<endl;
return 0;
}
P8663 [蓝桥杯 2018 省 A] 倍数问题
题目描述
众所周知,小葱同学擅长计算,尤其擅长计算一个数是否是另外一个数的倍数。但小葱只擅长两个数的情况,当有很多个数之后就会比较苦恼。现在小葱给了你 $n$ 个数,希望你从这 $n$ 个数中找到三个数,使得这三个数的和是 $K$ 的倍数,且这个和最大。数据保证一定有解。
输入格式
从标准输入读入数据。
第一行包括 $2$ 个正整数表示 $n$ 和 $K$。
第二行 $n$ 个正整数,代表给定的 $n$ 个数。
输出格式
输出一行一个整数代表所求的和。
输入输出样例 #1
输入 #1
4 3
1 2 3 4
输出 #1
9
说明/提示
【样例解释】
选择 $2$、$3$、$4$。
【数据约定】
对于 $30%$ 的数据,$n \le 100$。
对于 $60%$ 的数据,$n \le 1000$。
对于另外 $20%$ 的数据,$K \le 10$。
对于 $100%$ 的数据,$1 \le n \le 10^5$,$1 \le K \le 10^3$,给定的 $n$ 个数均不超过 $10^8$。
时限 1 秒,256M。蓝桥杯 2018 年第九届省赛。
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,k;
cin>>n>>k;
vector<vector<int>> v(k);
for(int i=1;i<=n;i++){
int x;
cin>>x;
v[x%k].push_back(x);
}
for(int i=0;i<k;i++)
sort(v[i].begin(),v[i].end());
int ans=0;
for(int i=0;i<k;i++){
for(int j=i+1;j<k;j++){
int e=(2*k-i-j)%k;
int len1=v[i].size();
int len2=v[j].size();
int len3=v[e].size();
if(e!=i&&e!=j){
if(len1<1||len2<1||len3<1) continue;
ans=max(ans,v[i].back()+v[j].back()+v[e].back());
}
else if(e==i){
if(len1<2||len2<1) continue;
ans=max(ans,v[j][len2-1]+v[i][len1-1]+v[i][len1-2]);
}
else if(e==j){
if(len1<1||len2<2) continue;
ans=max(ans,v[i][len1-1]+v[j][len2-1]+v[j][len2-2]);
}
else{
if(len1<3) continue;
ans=max(ans,v[i][len1-3]+v[i][len1-1]+v[i][len1-2]);
}
}
}
cout<<ans<<endl;
return 0;
}
P8712 [蓝桥杯 2020 省 B1] 整数拼接
题目描述
给定一个长度为 $n$ 的数组 $A_1,A_2,\cdots,A_n$。你可以从中选出两个数 $A_i$ 和 $A_j$($i\neq j$),然后将 $A_i$ 和 $A_j$ 一前一后拼成一个新的整数。例如 12
和 345
可以拼成 12345
或 34512
。注意交换 $A_i$ 和 $A_j$ 的顺序总是被视为 $2$ 种拼法,即便是 $A_i=A_j$ 时。
请你计算有多少种拼法满足拼出的整数是 $K$ 的倍数。
输入格式
第一行包含 $2$ 个整数 $n$ 和 $K$。
第二行包含 $n$ 个整数 $A_1,A_2,\cdots,A_n$。
输出格式
一个整数代表答案。
输入输出样例 #1
输入 #1
4 2
1 2 3 4
输出 #1
6
说明/提示
对于所有评测用例,$1\le n\le10^5$,$1\le k\le10^5$,$1\le A_i\le10^9$。
蓝桥杯 2020 第一轮省赛 B 组 I 题。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+10;
int mp[11][N];
int a[N];
signed main(){
int n,k;
cin>>n>>k;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++){
int t=10;
for(int j=1;j<=10;j++){
// cout<<a[i]%k*t%k<<endl;
mp[j][a[i]%k*t%k]++;
t=t*10%k;
}
}
int ans=0;
for(int i=1;i<=n;i++){
int len=to_string(a[i]).size();
ans+=mp[len][((-a[i])%k+k)%k];
}
for(int i=1;i<=n;i++){
int num=stoll(to_string(a[i])+to_string(a[i]));
if(num%k==0) ans-=1;
}
cout<<ans<<endl;
return 0;
}
特别需要注意的是需要使用stoll()
而不是stoi()
,stoi()
stoi
函数是 C++ 标准库中用于将字符串转换为整数的函数。它可以处理不同进制的数字字符串,并将其转换为十进制整数。如果字符串包含非数字字符,stoi
将抛出 invalid_argument
异常;如果转换后的数字超出 int
类型的范围,将抛出 out_of_range
异常
P8708 [蓝桥杯 2020 省 A1] 整数小拼接
题目描述
给定一个长度为 $n$ 的数组 $A_1,A_2,\cdots,A_n$。你可以从中选出两个数 $A_i$ 和 $A_j$($i\neq j$),然后将 $A_i$ 和 $A_j$ 一前一后拼成一个新的整数。例如 12
和 345
可以拼成 12345
或 34512
。注意交换 $A_i$ 和 $A_j$ 的顺序总是被视为 $2$ 种拼法,即便是 $A_i=A_j$ 时。
请你计算有多少种拼法满足拼出的整数小于等于 $K$。
输入格式
第一行包含 $2$ 个整数 $n$ 和 $K$。
第二行包含 $n$ 个整数 $A_1,A_2,\cdots,A_n$。
输出格式
一个整数代表答案。
输入输出样例 #1
输入 #1
4 33
1 2 3 4
输出 #1
8
说明/提示
对于 $30%$ 的评测用例 $1\le n\le1000$,$1\le k\le10^8$,$1\le A_i\le10^4$。
对于所有评测用例,$1\le n\le10^5$,$1\le k\le10^{10}$,$1\le A_i\le10^9$。
蓝桥杯 2020 第一轮省赛 A 组 H 题。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+10;
int a[N];
signed main(){
int n,k;
cin>>n>>k;
for(int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+n+1);
int l=1,r=n;
int ans=0;
while(l<=r){
int num=stoll(to_string(a[l])+to_string(a[r]));
if(num<=k) ans+=(r-l),l++;
else r--;
}
l=1,r=n;
while(l<=r){
int num=stoll(to_string(a[r])+to_string(a[l]));
if(num<=k) ans+=(r-l),l++;
else r--;
}
cout<<ans<<endl;
return 0;
}
P8744 [蓝桥杯 2021 省 A] 左孩子右兄弟
题目描述
对于一棵多叉树,我们可以通过“左孩子右兄弟”表示法,将其转化成一棵二叉树。
如果我们认为每个结点的子结点是无序的,那么得到的二叉树可能不唯一。换句话说,每个结点可以选任意子结点作为左孩子,并按任意顺序连接右兄弟。
给定一棵包含 $N$ 个结点的多叉树,结点从 $1$ 至 $N$ 编号,其中 $1$ 号结点是根,每个结点的父结点的编号比自己的编号小。请你计算其通过"左孩子右兄弟"表示法转化成的二叉树,高度最高是多少。(只有根结点这一个结点的树高度为 $0$)
例如如下的多叉树:
可能有以下 $3$ 种 (这里只列出 $3$ 种, 并不是全部) 不同的 “左孩子右兄弟” 表示:
其中最后一种高度最高, 为 $4$。
输入格式
输入的第一行包含一个整数 $N$ 。
以下 $N-1$ 行, 每行包含一个整数, 依次表示 $2$ 至 $N$ 号结点的父结点编号。
输出格式
输出一个整数表示答案。
输入输出样例 #1
输入 #1
5
1
1
1
2
输出 #1
4
说明/提示
对于 $30 %$ 的评测用例,$1 \leq N \leq 20$;
对于所有评测用例,$1 \leq N \leq 10^5$ 。
蓝桥杯 2021 第一轮省赛 A 组 H 题。
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int n;
int h[N],ne[N],to[N],idx=0;
void add(int a,int b){
to[++idx]=b;
ne[idx]=h[a];
h[a]=idx;
}
int dfs(int u){
int cnt_child=0;
int max_sub_depth=1;
for(int i=h[u];~i;i=ne[i]){
cnt_child++;
int v=to[i];
max_sub_depth=max(max_sub_depth,dfs(v));
}
if(cnt_child==0) return 1;
else return max_sub_depth+cnt_child;
}
int main(){
int n;
cin>>n;
memset(h,-1,sizeof h);
for(int i=2;i<=n;i++){
int x;cin>>x;
add(x,i);
}
cout<<dfs(1)-1<<endl;
return 0;
}