大概只能做出六七道的样子,菜菜的我也只能提供B、E、F、H、J、L几道题的题解啦。

B Bitwise Exclusive-OR Sequence

题目大意:给你n个数和m个关系,每个关系要求两个数ai⊕bi=mia_i⊕b_i=m_iai​⊕bi​=mi​,然后求解所以满足要求的n个数中∑i=1nai\sum_{i=1}^{n}a_i∑i=1n​ai​的最小值是多少。(n≤105,m≤2×105)(n\leq10^5,m\leq2×10^5)(n≤105,m≤2×105)
容易发现每个联通块中只要填好一个数,其它数的值也就唯一确定了,我们只需要按位枚举每个联通块中任意一个点的数值即可,因为位与位之间的异或值不会产生影响,故每一位都取最小值即可得到整体的最小值。

#include<iostream>
#include<cstdio>
#include<string>
#include<iostream>
#include<cstring>
#define int long long
#define maxn 1000005
using namespace std;int read()
{int x=1,res=0;char c=getchar();while(c<'0'||c>'9'){if(c=='-')x=-1;c=getchar();}while(c>='0'&&c<='9'){res=res*10+(c-'0');c=getchar();}return res*x;
}
struct edge{int next,to,dis;
}g[maxn<<1];
int n,m,aa,bb,cc,num,col,a[35],ans,pd;
int last[maxn],vis[maxn],f[maxn];void add(int from,int to,int dis)
{g[++num].next=last[from];g[num].to=to;g[num].dis=dis;last[from]=num;
}void dfs(int x,int val)
{vis[x]=1;col++;f[x]=val;for(int i=0;i<=30;i++)a[i]+=(val>>i)&1;for(int i=last[x];i;i=g[i].next){int v=g[i].to;if(vis[v]&&(f[x]^f[v])!=g[i].dis){pd=1;}if(!vis[v])dfs(v,val^g[i].dis);}
}signed main()
{n=read();m=read();for(int i=1;i<=m;i++){aa=read();bb=read();cc=read();add(aa,bb,cc);add(bb,aa,cc);}memset(vis,0,sizeof(vis));for(int j=1;j<=n;j++){if(vis[j]) continue;memset(a,0,sizeof a);col=0;dfs(j,0);for(int i=0;i<=30;i++){ans+=min(col-a[i],a[i])*(1<<i);}}if(pd==1) puts("-1");else cout<<ans;return 0;
}

E Edward Gaming, the Champion

题目大意,给定一个字符串,判断含有多少个edgnb。签到题。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
string a;
int ans;
int main()
{cin>>a;int len=a.size();for(int i=0;i<=len-5;i++){if(a[i]=='e'&&a[i+1]=='d'&&a[i+2]=='g'&&a[i+3]=='n'&&a[i+4]=='b')ans++;}cout<<ans;return 0;
}

F Encoded Strings I

题目大意:给你一个字符串,按照题目要求对该字符串的每一个前缀串进行变换,输出所有变换后的串中字典序最大的一个字符串。具体变换规则为:一个字符它最后出现的位置后有iii个不同的字符,那么该字符就应该变换成第i+1i+1i+1个字符。简单模拟即可

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#define int long long
#define maxn 1005
using namespace std;int n;
string a,b,c;
int f[maxn];void solve(int x)
{int cnt=0;memset(f,0,sizeof(f));b.clear();for(int i=x;i>=0;i--){if(f[a[i]-'a']) continue;f[a[i]-'a']=++cnt;}for(int i=0;i<=x;i++){b.insert(i,1,char(f[a[i]-'a']+'a'-1));}
}signed main()
{cin>>n;cin>>a;c="a";for(int i=0;i<n;i++){solve(i);if(b>c) c=b;}cout<<c<<endl;
}

J Luggage Lock

题目大意:给你一个四位密码锁,求最少多少次操作可以从起始状态转到目标状态。
对于每次询问如果直接bfs时间复杂度为O(104×T)O(10^4×T)O(104×T)很难在给定的时间限制内给出答案,但是我们发现从起始状态转移到目标状态相当于每位加或减一个数,而且如果每位进行的操作都相同时,答案一定相同,因此我们可以将起始状态和目标状态同时减去起始状态的数值,即(a,b)~(0,b-a)这样我们只需要知道从0开始到所有状态的操作次数即可,时间复杂度O(104+T)O(10^4+T)O(104+T)

#include<iostream>
#include<cstdio>
#include<string>
#include<queue>
#define int long long
#define maxn 1000005
using namespace std;int read()
{int x=1,res=0;char c=getchar();while(c<'0'||c>'9'){if(c=='-')x=-1;c=getchar();}while(c>='0'&&c<='9'){res=res*10+(c-'0');c=getchar();}return res*x;
}struct node{int a1,a2,a3,a4,cnt;
};int t,aa,bb,a[5],vis[10][10][10][10],f[10005];
queue<node>q;int cal(int a,int b,int c,int d)
{return a+b*10+c*100+d*1000;
}void bfs(){q.push((node){0,0,0,0,0});while(q.size()){node u=q.front();q.pop();if(vis[u.a1][u.a2][u.a3][u.a4]) continue; f[cal(u.a1,u.a2,u.a3,u.a4)]=u.cnt;vis[u.a1][u.a2][u.a3][u.a4]=1;int a=u.a1,b=u.a2,c=u.a3,d=u.a4,cnt=u.cnt;//1q.push((node){(a+1)%10,b,c,d,cnt+1});q.push((node){(a+9)%10,b,c,d,cnt+1});q.push((node){a,(b+1)%10,c,d,cnt+1});q.push((node){a,(b+9)%10,c,d,cnt+1});q.push((node){a,b,(c+1)%10,d,cnt+1});q.push((node){a,b,(c+9)%10,d,cnt+1});q.push((node){a,b,c,(d+1)%10,cnt+1});q.push((node){a,b,c,(d+9)%10,cnt+1});//2q.push((node){(a+1)%10,(b+1)%10,c,d,cnt+1});q.push((node){(a+9)%10,(b+9)%10,c,d,cnt+1});q.push((node){a,(b+1)%10,(c+1)%10,d,cnt+1});q.push((node){a,(b+9)%10,(c+9)%10,d,cnt+1});q.push((node){a,b,(c+1)%10,(d+1)%10,cnt+1});q.push((node){a,b,(c+9)%10,(d+9)%10,cnt+1});//3q.push((node){(a+1)%10,(b+1)%10,(c+1)%10,d,cnt+1});q.push((node){(a+9)%10,(b+9)%10,(c+9)%10,d,cnt+1});q.push((node){a,(b+1)%10,(c+1)%10,(d+1)%10,cnt+1});q.push((node){a,(b+9)%10,(c+9)%10,(d+9)%10,cnt+1});//4q.push((node){(a+1)%10,(b+1)%10,(c+1)%10,(d+1)%10,cnt+1});q.push((node){(a+9)%10,(b+9)%10,(c+9)%10,(d+9)%10,cnt+1});}
}signed main()
{t=read();bfs();while(t--){aa=read();bb=read();a[1]=(bb%10-aa%10+10)%10;a[2]=(bb/10%10-aa/10%10+10)%10;a[3]=(bb/100%10-aa/100%10+10)%10;a[4]=(bb/1000%10-aa/1000%10+10)%10;printf("%d\n",f[cal(a[1],a[2],a[3],a[4])]);}}

L Perfect Matchings

题目大意:给你一个完全图和该图中的一颗生成树,问不包括树边的边独立集的数目有多少。
题解:首先我们容易发现对于一个点数为2n2n2n的完全图,边独立集数目为sum=∏i=1n(2×i−1)sum=\prod_{i=1}^{n}(2\times i-1)sum=∏i=1n​(2×i−1),因此我们可以考虑采用容斥原理,问题转化为求含有树边的边独立集的数目,其次,如果我们选出了一些树边,那么剩下的点依旧能够形成一张完全图,这样我们就只需要求解树边的选取方案数即可,但这样做问题在于我们会选出重复的树边,因为当选取一些树边时,剩余结点形成的完全图中仍然还剩有树边,而通过完全图得到的结果显然会比答案要大,当我们选择iii条树边时,用上述方法求得的答案会多CkiC_{k}^{i}Cki​个选k(k>i)k(k>i)k(k>i)条树边的方案,不难看出选奇数条树边的方案数∗*∗剩余完全图选边方案数-选偶数条树边的方案数∗*∗剩余完全图选边方案数即为不符合题意的方案数,而求解选取树边的方案数可以通过树形dp实现,我们设f[i][j][1/0]f[i][j][1/0]f[i][j][1/0]表示以iii为根的子树选jjj条树边选或不选自己的方案数,则
f[x][k][0]=f[x][k][0]+f[x][k−j][0]∗(f[v][j][0]+f[v][j][1])f[x][k][1]=f[x][k][1]+f[x][k−j][1]∗(f[v][j][0]+f[v][j][1])f[x][k][1]=f[x][k][1]+f[x][k−j][0]∗f[v][j−1][0]f[x][k][0]=f[x][k][0]+f[x][k-j][0]*(f[v][j][0]+f[v][j][1])\\ f[x][k][1]=f[x][k][1]+f[x][k-j][1]*(f[v][j][0]+f[v][j][1])\\ f[x][k][1]=f[x][k][1]+f[x][k-j][0]*f[v][j-1][0]f[x][k][0]=f[x][k][0]+f[x][k−j][0]∗(f[v][j][0]+f[v][j][1])f[x][k][1]=f[x][k][1]+f[x][k−j][1]∗(f[v][j][0]+f[v][j][1])f[x][k][1]=f[x][k][1]+f[x][k−j][0]∗f[v][j−1][0]
然而这样的时间复杂度为O(n3)O(n^3)O(n3),我们可以通过统计每一个子树的大小来对dp进行优化,时间复杂度均摊为O(n2)O(n^2)O(n2)

#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#define int long long
#define maxn 4005
#define mod 998244353
using namespace std;int read()
{int x=1,res=0;char c=getchar();while(c<'0'||c>'9'){if(c=='-')x=-1;c=getchar();}while(c>='0'&&c<='9'){res=res*10+(c-'0');c=getchar();}return res*x;
}struct edge{int next,to;
}g[maxn<<1];
int f[maxn][maxn][2],aa,bb,ans;
int n,num,last[maxn],sum[maxn],sz[maxn],vis[maxn];void add(int from,int to)
{g[++num].next=last[from];g[num].to=to;last[from]=num;
}void dfs1(int x,int fa)
{sz[x]=1;for(int i=last[x];i;i=g[i].next){int v=g[i].to;if(v!=fa){dfs1(v,x);sz[x]+=sz[v];}}
}void dfs(int x)
{vis[x]=1;f[x][0][0]=1;for(int i=last[x];i;i=g[i].next){int v=g[i].to;if(!vis[v]){dfs(v);for(int k=sz[x]/2;k>=1;k--){for(int j=max(1ll,k+sz[v]/2-sz[x]/2);j<=min(sz[v]/2+1,k);j++){f[x][k][0]=(f[x][k][0]+(f[x][k-j][0]*(f[v][j][0]+f[v][j][1])%mod))%mod;f[x][k][1]=(f[x][k][1]+(f[x][k-j][1]*(f[v][j][0]+f[v][j][1])%mod))%mod;f[x][k][1]=(f[x][k][1]+(f[x][k-j][0]*f[v][j-1][0])%mod)%mod;}}}}
}signed main()
{n=read();sum[1]=1;sum[0]=1;for(int i=2;i<=n;i++) sum[i]=sum[i-1]*(2*i-1)%mod;for(int i=1;i<=(2*n-1);i++){aa=read();bb=read();add(aa,bb);add(bb,aa);}dfs1(1,0);dfs(1);ans=sum[n];for(int i=1;i<=n;i++){if(i%2==1) ans=(ans-(f[1][i][0]+f[1][i][1])*sum[n-i]%mod+mod)%mod;else ans=(ans+(f[1][i][0]+f[1][i][1])*sum[n-i]%mod+mod)%mod;}cout<<ans%mod;return 0;
}

H Line Graph Matching

题目大意:给你一个无向连通图,每次可以选取与一个顶点的相连的两条边并得到两条边的权值,得到的最大权值是多少。
题解:不难看出,当边数为偶数时,存在方案使得所以边都可以取完,答案即为边的权值之和,而边数为奇数时,我们必须要舍去一条边不去选,如果删除这条边后图依然连通,那么这个边就可以不选然后将其他边全选,而如果这条边是图的一条割边,我们就需要统计一些割边连通的两个非连通图的边数,如果都为偶数那么这条边就可以不选,如果都为奇数那么两个非连通图中必然又要有一些边不能选,如果这样答案一定不是最优解,直接舍去就可以,所以我们只需要删去一条非割边的边或者两侧的图都是有偶数条边的割边之中的权值最小的边即可,可以用tarjan算法求出割边,在tarjan过程中我们可以维护一下以某个点为根的子树的边数,而边数可以通过点的入度∑de[i]/2\sum de[i]/2∑de[i]/2得到。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#define int long long
#define maxn 400005
using namespace std;struct edge{int next,to,dis;
}g[maxn];
int dfn[maxn],low[maxn],num=1,last[maxn],n,m,c,tot,ans=2e9,a;
int bridge[maxn],aa,bb,cc,vis[maxn],de[maxn],sz1[maxn],sz2[maxn];int read()
{int res=0,x=1;char c=getchar();while(c<'0'||c>'9'){if(c=='-')x=-1;c=getchar();}while(c>='0'&&c<='9'){res=res*10+(c-'0');c=getchar();}return res*x;
}void add(int from,int to,int dis)
{g[++num].next=last[from];g[num].to=to;g[num].dis=dis;last[from]=num;
}void tarjan(int u,int id)
{dfn[u]=low[u]=++tot;for(int i=last[u];i;i=g[i].next){int v=g[i].to;if(!dfn[v]){tarjan(v,i);low[u]=min(low[u],low[v]);if(low[v]>dfn[u]){sz1[i]=sz1[i^1]=(de[v]-1)/2;sz2[i]=sz2[i^1]=m-sz1[i]-1;bridge[i]=bridge[i^1]=1;}de[u]+=de[v];}else if((i^id)!=1)low[u]=min(low[u],dfn[v]);}
}signed main()
{n=read();m=read();for(int i=1;i<=m;i++){aa=read();bb=read();cc=read();a+=cc;de[aa]++;de[bb]++;add(aa,bb,cc);add(bb,aa,cc);}if(m%2==0){cout<<a<<endl;return 0;}tarjan(1,0);for(int j=1;j<=n;j++)for(int i=last[j];i;i=g[i].next){if(bridge[i]==0) ans=min(ans,g[i].dis);else if((sz1[i])%2==0&&(sz2[i])%2==0) ans=min(ans,g[i].dis);}cout<<a-ans;return 0;
}

ICPC2021(沈阳)相关推荐

  1. 图论专题班连通性例题和练习

    2022牛客 图论 连通性(强连通.割点和桥) 文章目录 2022牛客 图论 连通性(强连通.割点和桥) 概念 双连通分量 强连通分量 tarjan 割点 割边(桥) tarjan求割点,桥 点双联通 ...

  2. 沈阳生态所在保护性耕作促进农业可持续发展方面取得新进展

    以免耕及秸秆覆盖还田为主的保护性耕作措施能够有效减轻土壤风蚀水蚀.提高土壤肥力和促进土壤有机碳截获.然而目前,保护性耕作对土壤微生物群落及其如何调控碳氮转化过程尚缺乏全面的认识,这决定着土壤健康和农田 ...

  3. MPB:沈阳生态所李琪组-​土壤线虫群落DNA提取、扩增及高通量测序

    为进一步提高<微生物组实验手册>稿件质量,本项目新增大众评审环节.文章在通过同行评审后,采用公众号推送方式分享全文,任何人均可在线提交修改意见.公众号格式显示略有问题,建议电脑端点击文末阅 ...

  4. 沈阳生态所揭示病原真菌和昆虫对温带森林木本植物物种共存的重要作用

    为什么形形色色的物种能够共同生活在一起?这背后隐藏着什么奥秘?该问题是群落生态学的核心问题之一.早期研究发现周围相同树种个体越多,其后代更新和存活表现越差,这种同种之间的相互抑制为其他种定植提供了生存 ...

  5. 沈阳农业大学计算机往年录取分数6,沈阳农业大学历年分数线 2021沈阳农业大学录取分数线...

    一.2019年沈阳农业大学各省录取分数线及录取位次统计表 1.沈阳农业大学2019年在青海录取分数线如下:文科录取批次本一批-分,最低录取位次为-名.理科录取批次本一批409分,最低录取位次为9557 ...

  6. 清华沈阳老师团队:元宇宙发展研究报告2.0版

    清华大学沈阳教授团队发布了<元宇宙发展研究报告2.0版>,总计205页.报告基于<元宇宙发展研究报告1.0版>,从元宇宙的缘起.概念与属性.技术与产业链.场景应用.风险点及治理 ...

  7. 沈阳建立通用航空产业基地,开辟国内首家无人机专用空域

    为了大力发展无人机产业基地,沈阳通用航空产业基地日前对外宣布,在原有基础上拓展并完善通航全产业链,正式开辟国内首家无人机专用空域. 图为沈阳法库通用航空产业基地实景 据介绍,该基地规划面积68平方公里 ...

  8. 沈阳构建智慧产业体系 大数据企业5年后将超200家

    近日,沈阳市对外公布了<沈阳市智慧产业发展规划(2016-2020年)>,全市计划构建具有全国领先水平的智慧产业体系,预计到5年后,全市的大数据企业有望超过200家. 据介绍,将开展以沈阳 ...

  9. 沈阳人才市场7月精品招聘会

    沈阳人才市场7月精品招聘会 7月1日    2008毕业生就业专场会暨技术.技能人才专场招聘会          (周二) 7月2日   建筑.装饰.建材.物业.房地产行业专场招聘会          ...

最新文章

  1. JOGL - Java与OpenGl的绑定(转)
  2. SAP、ORACLE、用友、金蝶四大ERP软件供应商的区别
  3. python bootstrap-fileinput示例_bootstrapfileinput实现文件自动上传
  4. 如何把a1的图纸变成a0_如何安装家用空开配电
  5. 生日快乐程序_别@官方了!云开发教你制作个性头像小程序,以后过节想加啥就加啥!...
  6. 用命令行执行java代码
  7. Git 切换提交历史节点
  8. Docker 容器遇到的乱码问题
  9. Ubuntu16.04安装Caffe(CPU Only)
  10. 为防盗装自动门 不想也会影响生活
  11. Oracle非常规恢复(使用BBED跳过归档)
  12. 消息队列(MQ):ZeroMQ基本原理
  13. 通俗易懂的MonteCarlo积分方法(六)
  14. x264源码下载信息
  15. 马尔科夫决策过程(MDP) : BlackJack (MC-Off Policy)
  16. python核心编程
  17. python scratch ev3_如何在scratch上连接乐高ev3?
  18. 谷歌账号无法与服务器建立连接服务器,谷歌市场无法与服务器建立可靠的数据连接怎么解决...
  19. 郑中基 英雄寞 08版射雕英雄传片头曲 LRC歌词
  20. AcWing 487. 金明的预算方案 (有依赖关系的背包问题)

热门文章

  1. mysql多表联合查询 去重_mysql中的多表联合并且去重排序
  2. 大数据这么火,什么是大数据呢?-大萝卜博客网
  3. 计算机系统实验六:程序的链接
  4. 如何投影一个纹理 (翻译:心蓝 潘李亮)
  5. python中continue的用法_关于Python中continue用法问题
  6. 身份证号校验(极简版)
  7. Unity Shader Lab 模型切线和法线
  8. 06_权限管理(黑)
  9. 006 window操作系统安装(GHO)
  10. linux批量修改文件名字