Codeforces Round #499 (Div. 2) DEF 题解

和轩少一起Virtual participation了这次比赛,A题读错题花了大量时间导致只有4题就滚粗了。

D. Rocket

题意:让你猜一个位置x,范围在1-m,每次你询问系统y,如果x<y,系统会回答-1,x=y回答0,x>y回答1,但是系统有可能会说假话,你只知道系统真假性的回答是周期n(n<=30),要求在至多60次询问找到 x 的值。(回答0肯定是真话)

思路:首先要把一个周期内把系统真假话给测出来,我先问系统n次 1,如果回答-1肯定是假话,回答 1 肯定是假话,接下来就可以直接二分答案了。

#include<bits/stdc++.h>
using namespace std;
int a[50];
int main()
{
	int n,m,k,p=-1;
	cin>>n>>k;
	for(int i=0;i<k;i++)
	{
		puts("1");
		cin>>a[i];
		if(a[i]==0)return 0;
	}
	int l=1,r=n,x;
	while(l<=r)
	{
		m=(l+r)/2;
		p++;
		p%=k;
		cout<<m<<endl;
		cin>>x;
		if(x==0)
		return 0;
		x=x*a[p];
		if(x==-1)r=m;
		else l=m+1;
	}
}

E. Border

题意:有n个数,你可以每个数有无数个,你可以任意选择一些数相加,再模 k 得到一个值d,求出所有不同的d,并且从小到大输出,

思路:其实很好想,假设我有无数个5和7,显然我可以得到的所有的d(0到k-1),因此只要求出这n个数的gcd就行了(直觉告诉我这是对的),d的值是gcd的倍数。

#include<bits/stdc++.h>
using namespace std;
int gcd(int a,int b)
{
	if(!b)return a;
	return gcd(b,a%b);
}
int main()
{
	int n,k,x;
	scanf("%d%d",&n,&k);
	int tmp=k;
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&x);
		tmp=gcd(tmp,x);
	}
	printf("%d\n",k/tmp);
	for(int i=0;i*tmp<k;i++)
	printf("%d ",i*tmp);
}

F. Mars rover

题意:有一颗n个节点的二叉树,每个叶子节点都有一个值(0或1),每个非叶子节点有一个位运算符号,假设节点 o 的位运算符号为 AND,那么 o 的值为左儿子的值 and 右儿子的值,依次求出叶子节点改变后(0变成1,1变成0),根节点1的值,每次叶子节点值改变是独立的。

思路:这个点有点意思,建立好二叉树后,我把每个节点都用 rt[ o ][ v] 标记,这个数组表示这个节点的值为 v 时,根节点的值是多少,这样我搜索的时候就自带记忆化,每次我从叶子节点往上搜索,搜到一个节点,要么是根,要么有标记就结束搜索,并且把得到的答案传给这条路径的所有节点,复杂度降低为n。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
int tp[maxn],s[maxn][2],val[maxn],ans;
int f[maxn],rt[maxn][2],vis[maxn],flag[maxn];
char op[10];
void dfs(int o)
{
	if(s[o][0])dfs(s[o][0]);
	if(s[o][1])dfs(s[o][1]);
	if(tp[o]==1)
	val[o]=val[s[o][0]]&val[s[o][1]];
	else if(tp[o]==2)
	val[o]=val[s[o][0]]|val[s[o][1]];
	else if(tp[o]==3)
	val[o]=val[s[o][0]]^val[s[o][1]];
	else if(tp[o]==4)
	val[o]=!val[s[o][0]];
}
void dfs2(int o,int v,int son)
{
	int fv;
	if(tp[o]==1)
	fv=v&val[s[o][!son]];
	else if(tp[o]==2)
	fv=v|val[s[o][!son]];
	else if(tp[o]==3)
	fv=v^val[s[o][!son]];
	else if(tp[o]==4)
	fv=!v;
	if(o==1||rt[o][fv]!=-1)
	{
		if(rt[o][fv]==-1)
		rt[o][fv]=fv;
		ans=rt[o][fv];
		return;
	}
	dfs2(f[o],fv,flag[o]);
	rt[o][fv]=ans;
}
int main()
{
	int n,u,v;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%s",op);
		rt[i][0]=rt[i][1]=-1;
		if(op[0]=='A')
		{
			scanf("%d%d",&u,&v);
			tp[i]=1;
			s[i][0]=u,s[i][1]=v;
			f[u]=i,f[v]=i,flag[v]=1;
		}
		else if(op[0]=='O')
		{
			scanf("%d%d",&u,&v);
			tp[i]=2;
			s[i][0]=u,s[i][1]=v;
			f[u]=i,f[v]=i,flag[v]=1;
		}
		else if(op[0]=='X')
		{
			scanf("%d%d",&u,&v);
			tp[i]=3;
			s[i][0]=u,s[i][1]=v;
			f[u]=i,f[v]=i,flag[v]=1;
		}
		else if(op[0]=='N')
		{
			scanf("%d",&u);
			tp[i]=4;
			s[i][0]=u;
			f[u]=i;
		}
		else
		{
			scanf("%d",&u);
			val[i]=u;
			vis[i]=1;
		}
	}
	dfs(1);
	for(int i=1;i<=n;i++)
	if(vis[i])
	{
		ans=-1;
		dfs2(f[i],!val[i],flag[i]);
		printf("%d",ans);
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长沙橘子猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值