题目链接:http://poj.org/problem?id=1012
题目描述:
这是一个约瑟夫问题的变形,题目意思是给定一个k(<14),表示前k个为好人,后k个为坏人,围成一个环,问确定一个最小的m,使得经过k次后,只剩下k个好人。
这题的k值很小,可以直接模拟m打表,其关键点就是如何确定下一个淘汰的人是谁,假设从0开始排序号,第一次淘汰的是m-1号,如果m-1<k,则m不合适,将m加1继续判断,若m-1>=k,表示淘汰的是坏人,那么重新标号:
开始:0 1 2 3 4 ....k k+1.....2*k-1
第一次:0 1 2 3 5 ...k k+1.....m-1 m ... 2*k-2
反正每次编号后好人都在前k个,因此只需要判断下一个淘汰的人序号是不是小于k即可。
因此有:dp[i] = (dp[i-1]+m-1) % (n-i+1) ; //表示第i次淘汰的序号。
#include<cstdio>
#include<iostream>
using namespace std ;
/*
int res[20] ;
void printTable(){
int dp[20] ;
for( int k = 1; k <= 15; k++ ){
int n = 2*k ;
dp[0] = 0 ;
int m = 1 ;
for( int i = 1; i <= k; i++ ){
dp[i] = (dp[i-1]+m-1) % (n-i+1) ;
if( dp[i] < k ){
m++ ;
i = 0 ;
dp[0] = 0 ;
}
}
res[k] = m ;
}
}
*/
int main(){
//freopen("1234.in","r",stdin) ;
//printTable() ;
int val[] = {0,2,7,5,30,169,441,1872,7632,1740,93313,459901,1358657,2504881,13482720,25779600} ;
int k ;
while( cin >> k && k ){
printf("%d\n",val[k]) ;
}
return 0 ;
}