文章目录

  • 出题人
  • A《关于508的门老是被反锁这件事》
    • 思路
    • AC代码
  • B 昆虫关系
    • 思路1:带权并查集
    • AC代码
    • 思路2:种类并查集
    • AC代码2
    • 思路3:二分图染色
    • AC代码3
  • C 谁输了谁请客干饭
    • 思路
    • AC代码
  • D 新年快乐!
    • 思路
    • AC代码
  • E 恐怖之夜:召唤仪式
    • 思路
    • AC代码
  • F 恐怖之夜:圣歌圣咏
    • 思路
  • G 圆桌会议
    • 思路
    • AC代码
  • H 消灭
    • 思路
    • AC代码
  • I Fibonacci
    • 思路
    • 打表程序
    • AC代码

出题人

ABD: 晋云涛
C: 袁红婷
EF:谢承洋
GH:温世民
I:徐垚
验题人:晋云涛
题解撰写人:晋云涛,此题解是我把所有的题目都做了一遍再来写的,由于水平有限,题解写得有问题的地方可以来找我,或者直接问出题人。

A《关于508的门老是被反锁这件事》

思路

bfs+优化,这道题测试组数很多,直接爆搜会超时的,所以我们需要考虑优化。
需要想清楚这一点:
先通过随意的旋转方法把S变为0000,然后用同样的方法,把T变为T2。将S变为T的过程,等价于将0000变为T2的过程,两者的最少开锁次数是一样的。
所以我们可以预处理出0000到所有其他状态的最少次数,这样即可通过

AC代码

#include<bits/stdc++.h>using namespace std;
const int N = 1e5+9;
unordered_map<string,int> st;
unordered_map<string,int> ans;
struct node
{string s;int step;
};
char s[10],t[10];
void bfs(){queue<node> q;q.push({"0000",0});st["0000"]=1;ans["0000"]=0;while(q.size()){auto tmp = q.front();q.pop();//枚举一次操作几位 for(int i=1; i<=4; ++i){//从哪里开始 for(int j=1; j<=4-i+1; j++){int l=j-1,r=j+i-2;//    cout<<l<<" "<<r<<endl;string s2=tmp.s;for(int k=l; k<=r; ++k) {                   int x=(tmp.s[k]-'0'+1+10)%10;s2[k]=x+'0';}//cout<<"s2 "<<s2<<endl;if(!st[s2]) q.push({s2,tmp.step+1}) , st[s2]=1,ans[s2]=tmp.step+1;s2=tmp.s;for(int k=l; k<=r; ++k) {int x=(tmp.s[k]-'0'-1+10)%10;s2[k]=x+'0';}// cout<<"s2 "<<s2<<endl;if(!st[s2]) q.push({s2,tmp.step+1}) , st[s2]=1,ans[s2]=tmp.step+1;;} }//  exit(0);}
}
int main()
{bfs(); //cout<<ans["1111"]<<endl;int n;cin>>n; while(n--){     scanf("%s %s",s+1,t+1);int num=0;string S="",T="";for(int i=1; i<=4; ++i){int x=s[i]-'0',y=t[i]-'0';y=(y-x+10)%10;t[i]=y+'0';T+=t[i];}//cout<<T<<endl;printf("%d\n",ans[T]);}
}

B 昆虫关系

这道题可以用带权并查集,种类并查集,二分图染色三种方法处理

思路1:带权并查集

如果做过食物链那道经典并查集题目的并且理解了的同学,做这道题简直so easy,这道题也是经典带权并查集板子题。
我们用0表示同性,1表示异性,跑带权并查集板子即可,注意取模

AC代码

#include<iostream>
#include<cstdio>
using namespace std;
const int N = 1e6+9;
int p[N*2];
int val[N];
int find(int x){if(x!=p[x]) {int t=p[x];p[x]=find(p[x]);val[x]=(val[x]+val[t])%2;}return p[x];
}
void merge(int a,int b,int c){int fa=find(a),fb=find(b);if(fa!=fb){p[fa]=fb;val[fa]=(val[b]+c-val[a]+2)%2;}
}
int main(){int t,ca=0;cin>>t;while(t--){int n,m;scanf("%d %d",&n,&m);for(int i=1; i<=n*2; ++i) p[i]=i,val[i]=0;bool ok=false;for(int i=0; i<m; ++i){int a,b;scanf("%d %d",&a,&b);int fa=find(a),fb=find(b);if(fa==fb){if((val[a]-val[b]+2)%2==0) ok=true;}else{merge(a,b,1);}}printf("Scenario #%d:\n",++ca);if(ok) printf("Suspicious bugs found!");else printf("No suspicious bugs found!");if(t) printf("\n\n"); }return 0;
}

思路2:种类并查集

[1,n][1,n][1,n] 表示同性,[n+1,2∗n][n+1,2*n][n+1,2∗n]表示异性,跑种类并查集板子

AC代码2

#include<iostream>
#include<cstdio>
using namespace std;
const int N = 1e6+9;
int p[N*2];
int find(int x){if(x!=p[x]) p[x]=find(p[x]);return p[x];
}
void merge(int a,int b){int fa=find(a),fb=find(b);if(fa!=fb) p[fa]=fb;
}
int main(){int t,ca=0;cin>>t;while(t--){int n,m;scanf("%d %d",&n,&m);for(int i=1; i<=n*2; ++i) p[i]=i;bool ok=false;for(int i=0; i<m; ++i){int a,b;scanf("%d %d",&a,&b);int fa=find(a),fb=find(b);if(fa==fb) ok=true;else{merge(a,b+n);merge(b,a+n);}}printf("Scenario #%d:\n",++ca);if(ok) printf("Suspicious bugs found!");else printf("No suspicious bugs found!");if(t) printf("\n\n"); }return 0;
}

思路3:二分图染色

  • a与b之间是异性,等价于a与b要被染成不同的颜色,出现矛盾等价于存在奇环,即不是二分图。比如1和2是异性,2和3是异性,3和1是异性,这里出现了奇环,所以不是二分图,所以有矛盾。
  • 所以可以用染色法判定是不是二分图,从而等价判定是否有矛盾。

AC代码3

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 1e6+9;
int e[N*2],ne[N*2],h[N*2],idx;
int col[N];
void add(int a,int b){e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
bool dfs(int p,int c){col[p]=c;for(int i=h[p]; i!=-1; i=ne[i]){int j=e[i];if(!col[j]){if(!dfs(j,3-c)) return false;}else if(col[j]!=3-c) return false;}return true;
}
int main(){int t,ca=0;cin>>t;while(t--){int n,m;memset(h,-1,sizeof h);memset(col,0,sizeof col);idx=0;scanf("%d %d",&n,&m);bool ok=true;for(int i=0; i<m; ++i){int a,b;scanf("%d %d",&a,&b);add(a,b),add(b,a);}for(int i=1; i<=n; i++){if(!col[i]){ok=dfs(i,1);if(!ok) break;}}printf("Scenario #%d:\n",++ca);if(!ok) printf("Suspicious bugs found!");else printf("No suspicious bugs found!");if(t) printf("\n\n"); }return 0;
}

C 谁输了谁请客干饭

思路

  • 本场签到题1,简单博弈,因为先手第一次最多可以拿n-1个糖果,以后的每一次,每个人都只能拿不超过之前的人拿的个数的奇数个
  • 所以先手第一次可以拿 n−2n-2n−2 个( n>2n>2n>2 ),那么后手只能拿1个,最后剩下一个先手拿,先手胜利。
  • 如果 n=2n=2n=2 ,显然后手胜利

AC代码

#include<bits/stdc++.h>using namespace std;int main(){int t;cin>>t;while(t--){int n;scanf("%d",&n);if(n>2) puts("qxj_qing_ke_gan_fan");else puts("yxz_qing_ke_gan_fan");}return 0;
}

D 新年快乐!

思路

本场签到题2,一张图胜过千言万语:

题目叫求第 KKK小的数其实就是个二进制转换,把1换成3就行了

AC代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define rep(i,x,y) for(int i=x; i<=y; i++)
#define per(i,x,y) for(int i=x; i>=y; i--)
const int N = 1e5+9;
int ans[N];
int main()
{ll n;cin>>n;int idx=0;while(n){ans[idx++]=n%2;n/=2;}per(i,idx-1,0) printf("%d",ans[i]?3:0);return 0;}

E 恐怖之夜:召唤仪式

思路

  • 题意应该很明确,就是对于每一个aia_iai​,求出数组中其他能整除它的数的个数。直接暴力循环必定超时。
  • 因为ai≤106a_i \leq 10^6ai​≤106, 我们从1 枚举到1e6, 对于每一个iii, 我们处理出它倍数即可,具体看代码
  • 时间复杂度:对于每一个iii ,枚举它的倍数,需要枚举ni\frac{n}{i}in​ 次 ,所有的数需要枚举 n∗∑i=1n1in* \sum^n_{i=1} \frac{1}{i}n∗∑i=1n​i1​ 次, 调和级数∑i=1n1i\sum^n_{i=1} \frac{1}{i}∑i=1n​i1​ 的时间复杂度是 log(n)log(n)log(n) 级别的。所以时间复杂度为 nlog(n)nlog(n)nlog(n),完美通过

AC代码

#include <bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int n,a[N],cnt[N],ans[N];int main() {int n;cin>>n;for(int i=1; i<=n; i++) scanf("%d",a+i),cnt[a[i]]++;for(int i=1; i<=1e6; i++){for(int j=i; j<=1e6; j+=i){ans[j]+=cnt[i];}}for(int i=1; i<=n; i++) printf("%d\n",ans[a[i]]-1);return 0;
}

F 恐怖之夜:圣歌圣咏

思路

组合数学

  • 首先从 mmm 个数里面选 n−1n-1n−1 个不同的数,选法有 Cmn−1C_m^{n-1}Cmn−1​种
  • 排除2个身高相同的人,选一个最高的人,有n−2n-2n−2种方法

G 圆桌会议

思路

基环树,拓扑排序,个人觉得有个大佬讲的十分好,于是就直接放他的博客了。
大佬博客

AC代码

#include<bits/stdc++.h>
#define rep(i,x,y) for(int i=x; i<=y; i++)
#define per(i,x,y) for(int i=x; i>=y; i--)
using namespace std;
const int N = 1e5+9;
int g[N];//存图
int d[N];//d[i]代表点i的入度为d[i]
vector<int> rg[N];//正向图
queue<int> q;
bool vis[N];
int n;
//拓扑排序删除树枝
void topsort() {rep(i,0,n-1) {if(d[i]==0) q.push(i);}while(q.size()){int p = q.front();q.pop();int np = g[p];d[np]--;if(d[np]==0) q.push(np);}
}
int dfs(int u){//cout<<u<<endl;int maxdep=1;if(rg[u].size()==0) return 1;rep(i,0,rg[u].size()-1){int nu = rg[u][i];if(!d[nu]) maxdep=max(maxdep,dfs(nu)+1); }return maxdep;
}
int main() {cin>>n;//输入存图,g[i]表示点 i喜欢和g[i]坐在一起//也就是点i到g[i]有一条边rep(i,0,n-1) {scanf("%d",&g[i]);d[g[i]]++;//入度 rg[g[i]].push_back(i);//反图 }//拓扑排序删除边 topsort();//接下来去找基环int ans1=0,ans2=0;rep(i,0,n-1){if(d[i]<=0) continue;//拓扑删边后基环上的点,入度肯定为1int cnt=1;//统计环上点的个数d[i]=-1;for(int j=g[i]; j!=i; j=g[j]){d[j]=-1;cnt++;}//  cout<<cnt<<'\n';//如果基环大小为2,那么找最长的链 if(cnt==2) ans1+=dfs(i)+dfs(g[i]);else ans2=max(ans2,cnt); //cout<<ans1<<'\n';} cout<<max(ans1,ans2)<<'\n';return 0;
}

H 消灭

思路

签到,排个序处理就行

AC代码

#include <bits/stdc++.h>
#define ll long long
#define rep(i,x,y) for(int i=x; i<=y; i++)
using namespace std;
const int N = 1e5+9;
int b[N];
int main()
{int n,m;cin>>n>>m;for(int i=1; i<=n; i++) scanf("%d",b+i);sort(b+1,b+n+1);ll sum=m;bool ok=1;rep(i,1,n){if(sum<b[i]) {ok=0;break;}sum+=b[i];}printf("%s",ok?"yes":"no");return 0;
}

I Fibonacci

思路

做为数学弱鸡的我铭记"数学上来先打表"的口诀,此题也是打表找规律,很好看出,算个签到题吧

打表程序

#include <bits/stdc++.h>
#define ll long long
#define rep(i,x,y) for(int i=x; i<=y; i++)
using namespace std;
const int N = 1e5+9;
ll f[N];
int main()
{f[0]=7,f[1]=11;for(int i=2; i<=50; i++){f[i]=f[i-1] + f[i-2];cout<<f[i]<<" ";if(f[i]%3==0) puts("1");else puts("0");}return 0;
}

1表示是3的倍数,0表示不是

AC代码

#include <bits/stdc++.h>
#define ll long long
#define rep(i,x,y) for(int i=x; i<=y; i++)
using namespace std;
const int N = 1e5+9;
ll f[N];
int main()
{int n;while(cin>>n){if(n<2) puts("no");else {if((n-2)%4==0) puts("yes");else puts("no");}}return 0;
}

2022年寒假训练赛(2020级)题解相关推荐

  1. 2022年寒假训练赛第5场

    A:三英战吕布 题目描述 程序员Kimi同学这几天在看<三国演义>.今天他看到了"三英战吕布"这一回. 话说在虎牢关前,张飞首先单独战吕布,几十个回合不分输赢:随后关羽 ...

  2. 2022年寒假训练赛第6场

    A: 数字排序 题目描述 给定n个正整数,每个正整数均不超过10000,请编写一个程序统计每个整数出现的次数,并按照出现次数从多到少的顺序输出. 输入 单组输入,每组两行. 第1行包含一个正整数n,n ...

  3. 2022年寒假训练赛第3场

    A:一二五八 题目描述 X星球有一个部落一直沿用着一套古老的货币.这套货币一共有四种面值,分别是1星.2星.5星和8星.X星人决定携带总金额为N星的货币来进行一次环球旅行,因为需要携带的物品实在太多太 ...

  4. QLU寒假训练赛题解合集

    为了节省版面: 1.所有寒假训练赛题解都集中在这一篇里 2.所有题解代码都可以直接点击题目链接查看 0115 A题:签到,输出n+1 B题:签到,从左端点向右找一段和小于0的区间,再从右往左找 C题: ...

  5. 20200203DLUT寒假训练赛div2-简单搜索专场

    20200203DLUT寒假训练赛div2-简单搜索专场 :比赛地址 A - Find The Multiple 简单的dfs水题,主要是取10x和10x+1两种情况,并且注意函数存储数字必须得用un ...

  6. 【2022 省选训练赛 Contest 17 A】字符串游戏(结论)

    字符串游戏 题目链接:2022 省选训练赛 Contest 17 A 题目大意 有一个字符串一开始是空的,两个人轮流操作在任意位置插入 0/1. 然后给你一个串 s,先手目标是使得 s 是字符串的子串 ...

  7. 长沙学院20级训练赛-原魔题解

    链接:登录-专业IT笔试面试备考平台_牛客网 来源:牛客网 题目描述 众所周知,原魔是全宇宙最好的游戏.最近原魔出了一个策划模拟器,许多魔鬼策划在里面疯狂彰显才能,尽情的虐待旅行者.有这么一个萌新策划 ...

  8. 2018-2019赛季多校联合新生训练赛第一场题解和补题(中石油)

    做这个题用了没多长时间就a了四道题,然后觉得我可以做出更多的时候突然发现别的都不太会了..到最后才拿到一个铜牌后来听说这些 都是2011年慈溪的小学奥赛题,瞬间心态崩了...这都大学了做小学题都这么费 ...

  9. 中国石油大学 2018-2019赛季多校联合新生训练赛第一场 题解与补题

    这场比赛是在18年12月,因为当时完全不敢用C++,感觉很遥远的样子-代码都是拿C实现的,许多地方其实也可以优化的. 问题 A: 录取分数线 时间限制: 1 Sec 内存限制: 128 MB 题目描述 ...

最新文章

  1. (59)逆向分析 KiSwapContext 和 SwapContext —— 线程切换核心代码
  2. 【转】 python socket向百度发送http长连接请求 并做搜索
  3. ITK:将像素缓冲区导入到图像中
  4. iOS13后添加SceneDelegate初始化window
  5. Python中IOBase详解
  6. Python3 高级编程技巧(部分)
  7. 【Dart学习】--Dart之正则表达式相关方法总结
  8. VS Newtonsoft的引用问题
  9. 时间linux防火墙策略,Linux防火墙简介 – iptables配置策略(示例代码)
  10. java-如何反编译
  11. 翻译任务中的BPE词表实践总结
  12. rhino6.5安装教程
  13. 如何查看硬盘对应的主板接口属性
  14. 华为手机备份的通讯录是什么文件_华为手机的联系人在哪个文件夹里?
  15. 察举科目-汉代察举制度的重要环节
  16. 大华视频实时调用视频
  17. ArcGIS入门教程(矢量编辑工作流程)
  18. 简述基于CPU的机器码运行过程
  19. 驱动谷歌浏览器执行用例时报错java.lang.IllegalStateException
  20. YOLO 系列损失函数

热门文章

  1. 吐血整理的IDEA个人配置
  2. 语音转文字转换器如何使用
  3. 三星note3怎样刷原生Android,变废为宝焕发青春100块的三星Note3刷MIUI系统教程
  4. Ubuntu18.04安装福昕阅读器(六十八)
  5. oracle创建用户分配权限
  6. 5G与LTE双连接技术架构的选择分析
  7. 云游戏能否终结下一代游戏主机?
  8. 生成式对话seq2seq:从rnn到transformer
  9. c# oledb 方式操作excel 简单
  10. python打印数字正方形_python打印空心正方形-女性时尚流行美容健康娱乐mv-ida网...