poj1012约瑟夫有关问题

poj1012约瑟夫问题

推出递推公式   f = (f + m - 1) % (2 * k - i);

若超时,需打表;

# include <stdio.h>
# include <stdlib.h>
# include <string>
# include <string.h>

int s[33];

int out(int m, int k) {
	int point = -1;
	int t = m;
	int tmp = k;
	while (k --) {
		m = t;
		while(m --) {
			while (!s[(++ point) % (s[30])]);
		}
		point = point % (s[30]);
		//if (s[point] <= tmp) return 0;
		printf ("%d ", s[point]);
		s[point] = 0;
	}
	return 1;
}

int pre (int k) {
	for (int i = 0; i < k * 2; ++ i) {
		s[i] = i + 1;
	}
}

int go (int n, int &point, int k) {
	while (n --) {
		while (!s[(++ point) % (k * 2)]);
	}
	if(point >= 2 * k)point -= 2 * k;
	int t = s[point];
	s[point] = 0;
	return  t;
}

int main () {
	int k;
int ans[]={2,7,5,30,169,441,1872,7632,1740,93313,459901,1358657,2504881};
	memset(s, 0, sizeof(int) * 30);
	for(;;) {
		scanf ("%d", &k);
		if (!k) return 0;printf("%d\n", ans[k - 1]);continue;
		s[30] = k * 2;
		for (int i = 1; ; ++ i) {
			int point = -1;
			int j;
			pre(k);
			for (j = 0; j < k; ++ j) {
				int tmp = i % (k * 2 - j);
				if (tmp == 0) tmp = 2 * k - j;
				if (go(tmp, point, k) <= k) break;
			}
			if (j == k) {
				printf ("%d ", i);
				//pre(k);
				//out(i, k);
				break;
			}
			/*
			int t = i % (k * 2);
			if (t <= k && t > 0) continue;
			//printf ("%d        ", i);
			go (k);
			if ( out(i, k) ) {
				printf ("%d\n", i);
				break;
			}
			*/
		}
	}
	return 0;
}



没打表的:

# include <stdio.h>
# include <stdlib.h>
# include <string>
# include <string.h>

int s[33];

int out(int m, int k) {
	int point = -1;
	int t = m;
	int tmp = k;
	while (k --) {
		m = t;
		while(m --) {
			while (!s[(++ point) % (s[30])]);
		}
		point = point % (s[30]);
		//if (s[point] <= tmp) return 0;
		printf ("%d ", s[point]);
		s[point] = 0;
	}
	return 1;
}

int pre (int k) {
	for (int i = 0; i < k * 2; ++ i) {
		s[i] = i + 1;
	}
}

int go (int n, int &point, int k) {
	while (n --) {
		while (!s[(++ point) % (k * 2)]);
	}
	if(point >= 2 * k)point -= 2 * k;
	int t = s[point];
	s[point] = 0;
	return  t;
}

int check(int m, int k) {
	int tmp = 0;
	for (int i = k * 2; i > k; -- i) {
		tmp = (tmp + m - 1) % i;
		if (tmp < k) return 0;
	}
	return 1;
}

int main () {
	int k;
	memset(s, 0, sizeof(int) * 30);
	for(;;) {
		scanf ("%d", &k);
		if (!k) return 0;
		//s[30] = k * 2;
		int flag = 0;
		int i;
		for (int x = 1; ; x++) {
			if (check(x * (k + 1),k)) {printf("%d\n", x * (k + 1)); break;};
			if (check(x*(k+1) + 1,k)) {printf("%d\n", x* (k + 1) + 1); break;}
			/*
			flag = 0;
			i = x * (k + 1);
here:
			//int point = -1;
			int j;
			int tmp = 0;
			//if (tmp <= k && tmp > 0) continue;
			//pre(k);
			//tmp = 0;
			for (j = 0; j < k; ++ j) {
				tmp = (i + tmp - 1) % (k * 2 - j);
				//if (tmp == 0) tmp = 2 * k - j;
				if (tmp < k)break;
				//if (go(tmp, point, k) <= k) break;
			}
			if (j == k) {
				printf ("%d ", i);
				//pre(k);
				//out(i, k);
				break;
			}
			if (!flag) {i = x * (k + 1) + 1; flag = 1;goto here; }
			*/
			/*
			int t = i % (k * 2);
			if (t <= k && t > 0) continue;
			//printf ("%d        ", i);
			go (k);
			if ( out(i, k) ) {
				printf ("%d\n", i);
				break;
			}
			*/
		}
	}
	return 0;
}