洛谷 P2348 题解

本题解同步于我的洛谷博客

本题思路:模拟。

首先我们容易发现,因为每位玩家至少需要 \(4\) 张牌,所以如果 \(k < n \times4\),那么输出无解。

然后我们可以看出,这道题的主要部分是在洗牌上。

于是我们观察洗牌后的顺序:

b[1] = a[k / 2 + 1];
b[2] = a[1];
b[3] = a[k / 2 + 2];
b[4] = a[2];
...
b[k - 1] = a[k];
b[k] = a[k / 2];
//其中 b 为洗牌后牌的花色,a 为洗牌前牌的花色

可以看出(其中 a 为洗牌前牌的花色,b 为洗牌后牌的花色):

\[b_i = a_{\frac{k}{2} + \lceil {\frac{i}{2}} \rceil} (i \ \bmod 2 == 1) \]

\[b_i = a_{\frac{i}{2}} (i \ \bmod 2==0) \]

所以,我们就可以模拟 \(m\) 次洗牌,然后再 \(O(k)\) 发牌。

时间复杂度为 \(O(mk)\)

AC 代码:

#include <iostream>
#include <cstdlib>
#include <string>
#include <cstdio>
using namespace std;
int n, k, m, p;
struct sgs {
	string a, b;
} c[100010], d[100010];
int main() {
	cin >> n >> k >> m >> p;
	if(k < n * 4) puts("Error:cards not enough"), exit(0); //判断无解情况
	for(int i = 1; i <= k; i ++) cin >> c[i].a >> c[i].b;
	for(int i = 1; i <= m; i ++) {
		for(int j = 2; j <= k; j += 2) { //模拟洗牌过程
			d[j].a = c[j / 2].a;
			d[j].b = c[j / 2].b;
			d[j - 1].a = c[k / 2 + j / 2].a;
			d[j - 1].b = c[k / 2 + j / 2].b;
		}
		for(int j = 1; j <= k; j ++) c[j] = d[j]; //每次洗完牌要更新原数组
	}
	for(int i = 1, tot = 0; i <= k, tot < 4; i ++) { //模拟出牌过程
		if((i - 1) % n + 1 == p) {
			cout << d[i].a << ' ' << d[i].b << endl;
			++ tot;
		}
	}
	return 0;
}
posted @ 2020-10-27 20:10  crp_cpp  阅读(108)  评论(3编辑  收藏  举报