Codeforces Round #647 (Div. 2) - Thanks, Algo Muse!

这里就补下BCD吧,这次打思路太慢了

传送门

B. Johnny and His Hobbies

主要思路: 首先看到是1 — 1024,那么直接枚举1 — 2048 ,看看是否符合条件即可(是否和原来的一样)

解题思路:
  • 首先枚举1 — 2048 这些数,然后直接与输入的值进行 ^ 异或操作,然后判断这个值是否在原本输入数据中,并且看是否有重复的
  • 主要是处理初始化,也没什么难的,暴力就ok
代码:
#include 
#include 
#include 
#include 

using namespace std;

typedef long long ll;

const int N = 20500;

int ans[N],b[N],a[N];

int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		int n;
		memset(b,0,sizeof b);
		memset(a,0,sizeof a);
		scanf("%d",&n);
		for (int i = 1; i <= n; i++){
			scanf("%d",&ans[i]);
			a[ans[i]] = 1;
		}
		int f = 0;
		for (int i = 1; i <= 2048; i++){
			f = 1;
			for (int j = 1; j <= n; j ++){
				b[ans[j]] = 0;
			}
			for (int j = 1; j <= n; j ++){
				int k = ans[j] ^ i;
				if (!a[k] || b[k]){
					f = 0;
					break;
				}
				b[k] = 1;
			}
			if (f == 1){
				printf("%d\n",i);
				break;
			}
		}
		if (f == 0){
			puts("-1");
		}
	}
    return 0;
}


C. Johnny and Another Rating Drop

主要思路: 规律递归题,首先要发现规律,二进制的倍数 2 * x + 1, 然后一层一层循环进行。

解题思路:
  • 首先画图找规律,图画的比较丑请见谅:

Codeforces Round #647 (Div. 2) - Thanks, Algo Muse!_第1张图片

  • 这里可以发现规律,对于二进制,那么我们就可以根据这个规律,进行递归处理(while),所以我们只要处理好每一位的二进制数即可。
代码:
#include 
#include 
#include 
#include 

using namespace std;

typedef long long ll;

const int N = 20500;

int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		ll n;
		scanf("%lld",&n);
		ll sum = 0, ans = 0;
		while(ans < n){
			ll a = 1, b = 1;
			while(a * 2  <= n - ans){
				a =a * 2;
				b = b * 2 + 1;
			}
			ans = ans + a;
			sum = sum + b;
		}
		printf("%lld\n",sum);
	}
    return 0;
}


D. Johnny and Contribution

主要思路: 首先题意比较难理解,理解好题意那就简单些了,只需bfs排着标记即可

解题思路:
  • 首先大体说下题意吧,读懂题意读了好久

  • 一开始是一个图的边,然后最后输入的是每个节点他们的优先级

  • 这里的优先级就是标记为多少,不能2个优先级相同的相邻,也不能跳着整优先级,比如 1 3相邻(这里wa了2发,没读好题),然后就输出谁先排序即可。

  • 然后就说下怎么做吧

  • 首先存入点的优先级,和他的编号:

for (int i = 1; i <= n; i++){
		scanf("%d",&ans[i].ord);
		ans[i].id = i;
	}
  • 然后排序:(优先级小的肯定先输出)
sort(ans + 1, ans + 1 + n, cmp);
  • 然后我们进行循环bfs,首先我们知道一个道理,就是如果我们当前点的优先级为1,那么他的边上的点的优先级为2(都++),
  • 然后判断当前点的优先级是否符合已标记的优先级:
if (w[t] == k){
	bfs(t,k);
}
  • 如果符合就进行bfs,然后我们对周围的点是当前优先级的++,因为肯定要++的,为了判断下个优先级是否符合条件,这个地方自己想一下,画下图
  • 然后最后输出即可,就是排序的顺序
代码:
#include 
#include 
#include 
#include 

using namespace std;

typedef long long ll;

const int N = 500010, M = 1000010;

int h[N], ne[M], e[M], w[M], idx ;
int cnt = 0;
int d[M]; // 记录出场循序

struct node{
	int id;
	int ord;
}ans[M];

bool cmp(node aa, node bb){
	if (aa.ord == bb.ord) return aa.id < bb.id;
	return aa.ord < bb.ord;
}

void add(int x, int y){
	e[idx] = y, ne[idx] = h[x], h[x] = idx++;
}

void bfs(int x, int y){
	for (int i = h[x]; i != -1; i = ne[i]){
		int j = e[i];
		if (w[j] == y) w[j] ++;
	}
}

int main(){
	memset(h,-1,sizeof h);
	int n, m;
	scanf("%d%d",&n,&m);
	int x, y;
	for (int i = 1; i <= m ; i++){
		scanf("%d%d",&x,&y);
		add(x,y), add(y,x);
	}
	for (int i = 1; i <= n; i++){
		scanf("%d",&ans[i].ord);
		ans[i].id = i;
	}
	int f = 1;
	sort(ans + 1, ans + 1 + n, cmp);
	for (int i = 1; i <= n; i++) w[i] = 1;
	for (int i = 1; i <= n; i ++){
		int t = ans[i].id;
		int k = ans[i].ord;
		d[i] = t;
		if (w[t] == k){
			bfs(t,k);
		}
		else{
			f = 0;
			break;
		}
	}
	if (f){
		for (int i = 1; i <= n; i++){
			printf("%d ",d[i]);
		}
		puts("");
	}
	else{
		puts("-1");
	}
    return 0;
}

你可能感兴趣的:(CodeForces,思维,递归)