Card Trick poj3032 软2的同学,还记得这道题吗

69 阅读1分钟

利用vector的解法

软二的同学们,还记得老师布置的POJ3032那道题吗?当时在学搜索,是练习搜索的。POJ3032 数据范围小 n <= 13。现在 n <= 20000。还用搜索肯定会超时,甚至搜不出来。最后面是我的解法,先给出正解。

利用一个容器维护剩余牌的数目及位置,O(1)时间内确定下一张牌的位置。\

CTRICK - Card Trick

#tree

\

The magician shuffles a small pack of cards, holds it face down and performs the following procedure:

  1. The top card is moved to the bottom of the pack. The new top card is dealt face up onto the table. It is the Ace of Spades.
  2. Two cards are moved one at a time from the top to the bottom. The next card is dealt face up onto the table. It is the Two of Spades.
  3. Three cards are moved one at a time…
  4. This goes on until the nth and last card turns out to be the n of Spades.

This impressive trick works if the magician knows how to arrange the cards beforehand (and knows how to give a false shuffle). Your program has to determine the initial order of the cards for a given number of cards, 1 ≤ n ≤ 20000.

Input

On the first line of the input is a single positive integer, telling the number of test cases to follow. Each case consists of one line containing the integer n.

Output

For each test case, output a line with the correct permutation of the values 1 to n, space separated. The first number showing the top card of the pack, etc…

Example

Input:
2
4
5

Output:
2 1 4 3
3 1 4 5 2

 Submit solution!

#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <vector>
using namespace std;
#define M 20005
int n;
int main()
{
	int t;
	scanf("%d", &t);
	while (t--) {
		scanf("%d", &n);
		vector<int>q(n + 2, 0);
		vector<int>pos(n + 2, 0);
		for (int i = 0; i <= n; i++)
			pos[i] = i;//存放位置
		int cur = 1, left = n;
		for (int i = 1; i <= n; i++) {
			cur = (cur + i) % left;
			if (cur == 0) cur = left;
			int des = pos[cur];
			q[des] = i;
			pos.erase(pos.begin() + cur);//位置用过后,就将其删去
			--left;
		}
		printf("%d", q[1]);
		for (int i = 2; i <= n; i++)
			printf(" %d", q[i]);
		printf("\n");
		q.clear();
		pos.clear();
	}
	return 0;
}


\

\

\

Card Trick 换了几种提交姿势,本地1.4s 限时3s+,TLE\

#include <cstdio>
#include <cstring>
#include <iterator>
#include <iostream>
#include <ctime>
using namespace std;
#define N 20007
int ary[N];
int main()
{
	//clock_t start = clock();
	ios::sync_with_stdio(false); //节约时间 
	int n;
	//freopen("data.in", "r", stdin);
	//freopen("data.out", "w", stdout);
	while(~scanf("%d", &n)) {
	//while(cin >> n) {
		int cnt = 1, cur = 0, left = n; //cur游标,cnt为要填入的数字 
		memset(ary, 0, sizeof ary);
		while(cnt <= n) {
			int k = 0, j = cnt % left; //j用于优化 
			while(k < j) { //寻找j个空格 
//				if (ary[cur] == 0)
//					k++;
				k += (!ary[cur]); // 节约时间 
				cur = (cur + 1) % n;
			}
			while(ary[cur] != 0) {//寻找下一个空,填数 
				cur = (cur + 1) % n; 
			}
			ary[cur] = cnt++;
			left--; 			 
		}
//		printf("%d", ary[0]); 
//		for (int i = 1; i < n; ++i) {
//			printf(" %d", ary[i]);
//		}
//		puts(""); //4.76 s
		copy(ary, ary + n - 1, ostream_iterator<int>(cout, " "));  
        cout << ary[n - 1] << endl; //实验证明这种流处理快些 
        
        //clock_t ends = clock(); //实验室台式机太好,本1.45s 
        //cout <<"Running Time : "<<(double)(ends - start)/ CLOCKS_PER_SEC << endl;
		
	}
	
	return 0;
}


\

\