第 46 届 ICPC 国际大学生程序设计竞赛亚洲区域赛(沈阳)


​ 线上正赛铜尾,有惊无险拿到铜牌,还行,符合预期。
传送门

E. Edward Gaming, the Champion

​ 题意:从一长串字符串中找出有多少子串是"edgnb"。

​ 题解:签到题,kmp暴力匹配随便过,有手就行。

​ edg确实nb

F. Encoded Strings I

​ 题意:……(不好解释就这样吧)

​ 题解:就是一个暴力纯模拟,按照题意一步步写就行了。

​ 第一题打得太爽了导致心态有点波动,思考和代码都有点混乱,调了很久才调出来,导致队伍掉到了铜牌线外。还是比赛经验太少了。

B. Bitwise Exclusive-OR Sequence

​ 题意:提供\(n\)个点和\(m\)个关系,每个关系给出\(u,v,w\),代表\(a_u⊕a_v=w\),其中\(⊕\)代表异或计算,找出所有元素满足关系条件的最小的和,或者说明这样的元素有无法构造的情况。

​ 题解:有点有关系显然是图论题,而且很容易观察出来这样的题都是牵一发而动全身(确定一个点即可确定整个图的情况),因此我们必须从图的整体入手考虑,以图为整体进行求解计算。容易把这个图简化为\(w=0或1\)的情况;在这种情况下,若\(w=0\)则相邻两点相同,反之则不同。我们可以想到二分图染色的方法来解决这题。

​ 代码:

#include<bits/stdc++.h>
using namespace std;

struct edge
{
	int u,v,w,nxt;
}e[400003];
int h[200003],etot;

void adde(int u,int v,int w)
{
	e[++etot].u=u,e[etot].v=v,e[etot].w=w,e[etot].nxt=h[u],h[u]=etot;
}

bool v[200003],se[200003];
int cnt[2];

void dfs(int f,int s,int ws,bool sse)
{
	v[s]=1;se[s]=sse;cnt[sse]++;
	for(int i=h[s];i;i=e[i].nxt)
		if(e[i].v!=f)
		{
			int tse=((e[i].w>>ws)&1)?(!sse):sse;
			if(v[e[i].v])
			{
				if(tse!=se[e[i].v])
				{
					cout<<"-1";
					exit(0);
				}
				else
					continue;
			}//visited
			dfs(s,e[i].v,ws,tse);
		}
}

int n,m;

int main()
{
	cin>>n>>m;
	for(int i=1;i<=m;i++)
	{
		int t1,t2,t3;
		scanf("%d%d%d",&t1,&t2,&t3);
		adde(t1,t2,t3);
		adde(t2,t1,t3);
	}
	long long ans=0;
	for(int i=0;i<=30;i++)
	{
		cnt[0]=0,cnt[1]=0;
		memset(v,0,sizeof(v));
		memset(se,0,sizeof(se));
		for(int j=1;j<=n;j++)
		{
			if(!v[j])
				dfs(0,j,i,0);
			ans+=min(cnt[0],cnt[1])*pow(2,i);
			cnt[0]=0,cnt[1]=0;
		}	
	}
	cout<<ans;
	return 0;
}

​ 这题比赛思考和写代码都挺顺利的,写完编译一遍过,样例一遍过,队友造的hack一遍过(事实证明队友没造好),没想到还是wa了两发,而且第二发是在未经仔细思考的情况下直接交的(着实是我自己贡献的罚时)。本来没有这么惊险的。

J. Luggage Lock

​ 题意:行李箱上的锁有四位,一次操作只能使连续的一个或者多个数字向上或者向下移动一次(注意行李箱的数字是循环的而且是从零到九)。给出目前状态和需要调整到的密码,问最少用多少次操作。

​ 题解:考场上写的是一个奇怪的搜索。先是确定差值,然后计算如何最快堆成差值的形状(堆小山入门题了)。一开始想到的差值只有十六种,以为对于任何一种情况都转一圈之内才是最好的,但是wa了。改了前后三圈总共差值625种才搜过去,也没看到底是哪个样例这么阴间。

​ 代码:

#include<bits/stdc++.h>
using namespace std;

int a[5],b[5],c[5];
int sgn(int x)
{
	if(x<0) return -1;
	if(x==0) return 0;
	return 1;
}

int getans()
{
	int maxn=0,ans=0;
	for(int i=1;i<=4;i++)
	{
		if(sgn(a[i]==0)) continue;
		else if(sgn(a[i])==sgn(a[i-1])) 
		{
			if(abs(a[i])>maxn)
				ans+=abs(a[i])-maxn;
			maxn=abs(a[i]);
		}
		else  ans+=abs(a[i]),maxn=abs(a[i]);
	}
	return ans;	
}

int reans=9999999;

void dfs(int ws)
{
	if(ws==5)
	{
		reans=min(reans,getans());
	}
	else
	{
		a[ws]=c[ws]-b[ws];
		dfs(ws+1);
		a[ws] -= 10, dfs(ws + 1);
		a[ws] -= 10, dfs(ws + 1);
		a[ws] += 30, dfs(ws + 1);
		a[ws] += 10, dfs(ws + 1);
	}
}

void solve()
{
	int tmp1,tmp2;
	scanf("%d%d",&tmp1,&tmp2);
	for(int i=4;i;i--)
		b[i]=tmp1%10,tmp1/=10;
	for(int i=4;i;i--)
		c[i]=tmp2%10,tmp2/=10;
	
	dfs(1);
	printf("%d\n",reans);
}

int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		reans=9999999;
		solve();	
	}
}

​ 经过四五十种样例测试全对的我几乎已经失去希望,但是我的好队友发现了最后的bug并且完成最后一击,在此特别感谢我的队友!

其他题有点难,考察内容不太常考来着,就先这样吧,期待下周更好的表现。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM