PKU 1012
Joseph
とりあえず書いてみたプログラムだとTLEになるけどkの幅が小さいので、↓のプログラムで全ての場合を計算し、
#include <iostream> #include <vector> using namespace std; int main() { for ( int k=1; k<14; k++ ) //int k; //while ( cin >> k && k > 0 ) { int m; for ( m=1; ; m++ ) { vector<bool> guy( 2*k ); int p = -1; int i; for ( i=0; i<k; i++ ) { int t = (m-1) % (2*k-i) + 1; for ( int j=0; j<t; j++ ) { do p = ( p + 1 ) % (2*k); while ( guy[p] ); } guy[p] = true; if ( p < k ) break; } if ( i >= k ) break; } cout << m << endl; } return 0; }
↓のプログラムでOK。
#include <iostream> using namespace std; int main() { int ans[] = { 0, 2, 7, 5, 30, 169, 441, 1872, 7632, 1740, 93313, 459901, 1358657, 2504881 }; int k; while ( cin >> k && k > 0 ) cout << ans[k] << endl; return 0; }
真っ当な解法はどんなのだろうか。
- 実は真面目にシミュレートする必要がない
- k-1人目を殺したあとk人目に移るときを考えると m = 0 or 1 (mod k+1)
で高速化できたがまだ間に合わない。
答えをキャッシュしておくのが想定解法なのだろうか?
#include <iostream> #include <vector> #include <time.h> using namespace std; bool check( int m, int k ); int main() { int ans[14] = { 0 }; int k; while ( cin >> k && k > 0 ) { for ( int m=0; ans[k]==0; m+=k+1 ) { if ( check( m, k ) ) ans[k] = m; if ( check( m+1, k ) ) ans[k] = m + 1; } cout << ans[k] << endl; } return 0; } bool check( int m, int k ) { int p = 0; for ( int i=0; i<k; i++ ) { p += m - 1; p %= 2 * k - i; if ( p < k ) return false; } return true; }