POJ 3629 Card Stacking(队列,两种方法)

Card Stacking
http://poj.org/problem?id=3629

Time Limit:  1000MS
Memory Limit: 65536K


Description

Bessie is playing a card game with her N-1 (2 ≤ N ≤ 100) cow friends using a deck with K (N ≤ K ≤ 100,000; K is a multiple of N) cards. The deck contains M = K/N "good" cards and K-M "bad" cards. Bessie is the dealer and, naturally, wants to deal herself all of the "good" cards. She loves winning.

Her friends suspect that she will cheat, though, so they devise a dealing system in an attempt to prevent Bessie from cheating. They tell her to deal as follows:

1. Start by dealing the card on the top of the deck to the cow to her right

2. Every time she deals a card, she must place the next P (1 ≤ P ≤ 10) cards on the bottom of the deck; and

3. Continue dealing in this manner to each player sequentially in a counterclockwise manner

Bessie, desperate to win, asks you to help her figure out where she should put the "good" cards so that she gets all of them. Notationally, the top card is card #1, next card is #2, and so on.

Input

* Line 1: Three space-separated integers: NK, and P

Output

* Lines 1..M: Positions from top in ascending order in which Bessie should place "good" cards, such that when dealt, Bessie will obtain all good cards.

Sample Input

3 9 2

Sample Output

3
7
8

题意抽象:

1到K共K个数,做如下操作:从1开始,取出第一个数,然后把剩下P (1 ≤ P ≤ 10) 个数放到数列末尾,

记下第λN次取出的牌(2 ≤ N ≤ 100,N ≤ K ≤ 100,000,1 ≤ λ ≤ K/N),然后按升序输出。


思路:

可用队列模拟,注意退出循环的条件。

也可以用数组,较队列快。

复杂度:O(KP)


先放上用队列的代码:(慢死了)

/*969ms,1892KB*/

#include<cstdio>
#include<queue>
#include<algorithm>
#define MAXN 50002
using namespace std;

int ans[MAXN];

int main(void)
{
	int n, k, p;
	while (~scanf("%d%d%d", &n, &k, &p))
	{
		queue<int> q;
		for (int i = 1; i <= k; i++)
			q.push(i);
		////////////////////
		int cur = 1, sum = 0;
		while (true)
		{
			if (cur++ % n == 0)
			{
				ans[sum++] = q.front();
				if (sum == k / n)//注意sum是从0开始的
					break;
			}
			q.pop();
			for (int j = 0; j < p; j++)
			{
				q.push(q.front());
				q.pop();
			}
		}
		sort(ans, ans + sum);
		for (int i = 0; i < sum; i++)
			printf("%d\n", ans[i]);
	}
}



用数组写的代码,少了入列出列的操作,明显快多了:

/*125ms,464KB*/

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int maxn = 50002, maxm = 100002;
int n, k, p, ans[maxn];
bool vis[maxm];//卡片是否被拿走

//返回下一个被拿走的牌
int GetNext(int now)
{
	int count = 0;
	while (true)
	{
		if (!vis[now] && (++count == p + 1))
			return now;
		if (++now > k)
			now = 1;//再从头检索一遍
	}
}

int main(void)
{
	while (~scanf("%d%d%d", &n, &k, &p))
	{
		memset(vis, 0, sizeof(vis));
		int cur = 0, now = 1;
		for (int i = 1; i < k; i++)
		{
			vis[now] = true;
			if (i % n == 0)
				ans[cur++] = now;
			now = GetNext(now);
		}
		ans[cur++] = now;
		sort(ans, ans + cur);
		for (int i = 0; i < cur; i++)
			printf("%d\n", ans[i]);
	}
	return 0;
}


你可能感兴趣的:(ACM,STL,poj)