Codeforces Round #847 (Div. 3)

E. Vlad and a Pair of Numbers

思路:

1,a^b==x==(a+b)/2==( (a+b)>>1 ),从二进制的角度,只要x第第i位x[i]=1,则b[i]或者a[i]必是一个1一个0。为了方便构造,我们可以把x有1的部分都给a

2,(x<<1)==(a+b),我们当前的a是x,b是0,那么我们设法修改a,b使其相加的值为x左移一位。

因为我们要保证a^b结果不变,所以修改a[i]与 b[i]只能同时为1,或者同时为0。

如果(x<<1)的第i位是1,即a的第i-1位是1,我们要使其左移,可以修改a[i-2]=1,b[i-2]=1,前提是a[i-2]与b[i-2]原本是0。即x是不能有连续的1存在的,否则构造不出a,b。

3,如果可以构造出,会发现,a的每个1后面都会加上1,那么其实整体就是加上x>>1,所以a=x+x>>1,b=x>>1。

#include <bits/stdc++.h>
using namespace std;
#define ll     long long
typedef unsigned long long ull;
typedef pair<long long, long long> pll;
typedef pair<int, int> pii;

//double 型memset最大127,最小128
//std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
const int INF = 0x3f3f3f3f;         //int型的INF
const ll llINF = 0x3f3f3f3f3f3f3f3f;//ll型的llINF
const int N = 2e5 + 10;

void msolve()
{
	int x;
	cin >> x;
	if (x & 1)//x奇数显然无法构造
		{
			cout << -1 << endl;
			return;
		}
	else
		{
			int k = x >> 1;
			if ((k & x))//合法的构造即x必须没有连续的1,这样的他与右移一位的自己&得出是0,否则就一定不是0
				{
					cout << -1 << endl;//不是0说明无法构造
					return ;
				}
			cout << x / 2 * 3 << ' ' << x / 2 << endl;
		}
}

int main()
{
	int t;
	cin >> t;
	while (t--)
		{
			msolve();
		}

	return 0;
}

F. Timofey and Black-White Tree

思路:

就是数上跑最短路,重点优化就是不去跑已经大于答案的点。

1,我们用dis[i]表示从i点出发到达任意黑点的最短距离(i自己可以不用是黑点)。

2,显然,在不断更新中,我们一直都使所有dis[i]都表示到任意黑点最短距离,当我们把i变为黑点时,dis[i]就变为这个黑点与所有黑点中的最短距离

#include <bits/stdc++.h>
using namespace std;
#define ll               long long
#define endl             "\n"
#define endll            endl<<endl
typedef unsigned long long ull;
typedef pair<long long, long long> pll;
//---------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------//
const int INF = 0x3f3f3f3f;         //int型的INF
const ll llINF = 0x3f3f3f3f3f3f3f3f;//ll型的llINF
const int N = 2e5 + 100;

int head[N << 1], dis[N],  c[N];
int num;
int n;
int ans;
struct node
{
	int next, to;
} edge[N << 1];

void add(int u, int v)
{
	edge[++num].next = head[u];
	edge[num].to = v;
	head[u] = num;
}

void init()
{
	memset(head, 0, sizeof(head));
	memset(dis, 0x3f, sizeof(dis));
	num = 0;
	ans = INF;
}

void dijksta(int k)
{
	queue<int>q;
	q.push(k);
	ans = min(ans, dis[k]);//当把k设立为黑点,dis[k]表示一个黑点间距离,与ans取min
	dis[k] = 0;//然后我们以这个k黑点为起点,更新其他点到他的距离(如果到k的距离比那个点到已有黑点距离小的话)
	while (!q.empty())
		{
			int u = q.front();
			q.pop();
			if (dis[u] + 1 >= ans)continue;//核心剪枝,如果大于目前答案,无需继续深入
			for (int i = head[u]; i; i = edge[i].next)
				{
					int v = edge[i].to;
					if (dis[v] > dis[u] + 1)//到u这个黑点距离小,更新
						{
							dis[v] = dis[u] + 1;
							q.push(v);
						}
				}
		}
}

void mysolve()
{

	cin >> n;
	init();
	int u, v;
	for (int i = 1; i <= n; ++i)cin >> c[i];
	for (int i = 1; i < n; ++i)
		{
			cin >> u >> v;
			add(u, v);
			add(v, u);
		}
	for (int i = 1; i <= n; ++i)//i==1,只是建立c0,铺设所有点都源点的最短距离
		{
			dijksta(c[i]);
			if (i > 1)
				{
					cout << ans;
					if (i == n)cout << endl;
					else cout << ' ';
				}
		}

}

int32_t main()
{
	std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	ll t;
	cin >> t;
	while (t--)
		{
			mysolve();
		}
	system("pause");
	return 0;
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值