Codeforces Round #658 (Div. 2)

Codeforces Round #658 (Div. 2)

A. Common Subsequence

题意:

找两个字符串最短的公共子序列

题解:

用桶排序记录有是否出现过,出现过就输出

代码:

#include 
#include 
using namespace std;

int a[1005];
int b[1005];
int num[1005];

int main() {
	int t, n, m;
	cin >> t;
	while(t--) {
		memset(num,0,sizeof(num));
		bool F = false;
		int ans = 0;
		cin >> n >> m;
		for(int i = 1; i <= n; i++) {
			cin >> a[i];
			num[a[i]]++;
		}
		for(int i = 1; i <= m; i++) 
		cin >> b[i];
		for(int i = 1; i <= m; i++) {
			if(F)
			break;
			if(num[b[i]] != 0) {
				F = true;
				ans = b[i];
			}
		} 
		if(F) {
			cout << "YES" << endl;
			cout << "1 " << ans << endl;
		}
		else
		cout << "NO" << endl;
	}
	return 0;
} 

B. Sequential Nim

题意:

给你一堆数组, A 和 B 从第一个非0的数组中选,可以拿一个甚至多个,但一次只能在一堆拿,谁最先拿不下就输了,输出胜者;

题解:

谁先拿谁有优势,判断数组前面有几个一(全部为一的情况另外考虑),到不唯一的情况下是谁先手谁就赢:

代码:

#include 
using namespace std;

int a[100005];

int main() {
	int t, n, num;
	cin >> t;
	while(t--) {
		int head = 1;
		bool F = true;
		cin >> n;
		for(int i = 1; i <= n; i++) {
			cin >> a[i];
		}
		for(int i = 1; i <= n; i++) {
			if(head == 1 && a[i] == 1) {
				if(i == n) {
					continue;
				} else
				F = !F;
			} 
			else {
				head = 0;
			}
		}
		if(F)
		cout << "First" << endl;
		else
		cout << "Second" << endl;
	}
	return 0;
}

C1. Prefix Flip (Easy Version)

题意 :

给你一个01字符串,你每次可以翻转一个索引前的所有字符,然后再前后翻转,要使最后和给定的字符串一样,输出翻转的次数和索引。(答案可以不唯一)

题解:

Easy 的范围是在3n的范围内找出这个答案,可以一个接一个地解决这些问题。也就是说,使s1=t1,然后使s2=t2,等等。为了固定位i(当si≠ti),我们可以翻转长度i的前缀,然后翻转长度为1的前缀,再次翻转长度为i的前缀。这三个操作不会改变s中的任何其他位。因为我们每次使用3个操作,所以我们总共最多使用3n个操作。

代码:

#include 
#include 
using namespace std;

string a, b;

int main() {
	int t, n;
	cin >> t;
	while(t--) {
		cin >> n >> a >> b;
		vector<int> v;
		for(int i = 0; i < n; i++) {
			if(a[i] != b[i]) {
				if(i > 0)
				v.push_back(i+1);
				v.push_back(1);
				if(i > 0)
				v.push_back(i+1);
			}
		}
		cout << v.size() << " ";
		for(int i = 0; i < v.size(); i++) {
			cout << v[i] << " ";
		}
		cout << endl;
	}
}
 

C2. Prefix Flip (Hard Version)

题意:

同上(n的范围改成2n)

题解:

可以让a先变为全0或者全1,然后我们发现最后是1还是0取决于最后一位是0还是1,然后让b也变为全0或者全1,然后把路径反转

代码:

#include 
#include 
using namespace std;

const int MAXN = 1e5+10;
int a[MAXN];
int b[MAXN];
int ans[2*MAXN];

int main()  {
	int t, n;
	cin >> t;
	while(t--) {
		scanf("%d",&n);
		int cnt = 0;
		int pos = 1;
		for(int i = 1; i <= n; ++i) {
			scanf(" %c", &a[i]);
			a[i] -= '0';
		}
		for(int i = 1; i <= n; ++i) {
			scanf(" %c", &b[i]);
			b[i] -= '0';
		}
		for(int i = 1; i <= n; i++) {
			if(b[n-i+1] == (a[pos]+i-1)%2)
			ans[cnt++] = 1;
			ans[cnt++] = n-i+1;
			if(pos <= n/2)
			pos = n-pos+1;
			else
			pos = n-pos+2;
		}
		cout << cnt << " ";
		for(int i = 0; i < cnt; i++)
		cout << ans[i] << " ";
		cout << endl;
	}
	return 0;
}

D. Unmerge

01背包问题

你可能感兴趣的:(Codefoces,题解,算法)