題意:
略
分析:
如果使用單純模擬的話,時間複雜度會比較大
這裡運用了DP的思想,如果知道1 到 n-1個人和k,最後退出的人的序號,那麼通過這個序號可以推算出1到n個人k的最後推出的人的序號
還不懂的建議自己去磨一下.
Code:
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
const int MAXN = 500000;
int arr[10];
int location(int n, int k)
{
int cnt = 0;
vector<int> rst;
memset(arr, 0, sizeof(arr));
while( rst.size() < n ) {
cnt = 0;
for(int i = 1; ;) {
if( !arr[i] ) {
cnt += 1;
if( cnt == k ) {
arr[i] = 1;
rst.push_back(i);
break;
}
}
i = i+1;
if( i > n ) {
i = 1;
}
}
}
return rst[0];
}
int dp(int n, int k, int base)
{
int cur, pre = location(base, k);
for(int i = base+1; i <= n; i ++) {
cur = (pre+k)%i;
if( !cur ) {
cur = i;
}
pre = cur;
}
return cur;
}
int main(int argc, char **argv)
{
#ifndef ONLINE_JUDGE
freopen("test.in", "r", stdin);
#endif
int n, k, cas;
scanf("%d", &cas);
for(int z = 1; z <= cas; z ++) {
scanf("%d %d", &n, &k);
printf("%d %d %d\n", dp(n, k, 3), dp(n, k, 2), dp(n, k, 1));
}
return 0;
}