要求最后一位数的话比较简单,直接 f[ n ] = (f[n-1 ] +k )%n;原因很简单,f[n]的第一个数的位置为k-1;去掉该元素剩下的从k开始重新编号记为0-n-2
则f[n-1]的解的位置应该是 (f[n-1]+k)%n即f[n]的解;
由于我用的比较笨的方法,求倒数第二个数和第三个数都是和第一个数一个思路,程序写的叫繁杂而且系数较大,for example ,求倒数第二个数的之后先确定前两个数字的位置
那么剩下的重排就是f[n-2]的解;然后在算出该解对应原n个数中的位置;
但是这样想的实现如下,先展示较笨的我写的第一版本;
#include <cstdio>
#include <map>
#include <cmath>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 500100;
int f[maxn],f2[maxn],f3[maxn];
int debug(int a,int b,int lim);
void get_num(int& t,int t1,int t2,int i,int k){
int add = (k-1)%(i-2);
if(t1 < t2){
int first = i-1-t2+t1;
if(add < first)
t = (t2+1+add)%i;
else t = (t2+1+1+add)%i;
}
else {
int first = t1-t2-1;
if(add < first)
t = (t2+1+add)%i;
else t = (t2+1+1+add)%i;
}
}
int main()
{
int n,k;
int T;
scanf("%d",&T);
while(T--){
scanf("%d %d",&n,&k);
f[1] = 0;
for(int i=1;i<=n;i++) f[i]=(f[i-1]+k)%i;
f2[2] = debug(2,k,1);
f2[3] = debug(3,k,2);
for(int i=4;i<=n;i++){
int t1 = (k-1)%i;
int t2 = (t1+1+(k-1)%(i-1))%i;
int first;
if(t1 < t2){
first = i-1-t2+t1;
} else first = t1-t2-1;
if(f2[i-2] < first){
f2[i] = (f2[i-2]+t2+1)%i;
}
else f2[i] = (f2[i-2]+t2+2)%i;
}
f3[3] = debug(3,k,1);
f3[4] = debug(4,k,2);
f3[5] = debug(5,k,3);
for(int i=6;i<=n;i++){
int t1 = (k-1)%i;
int t2 = (t1+1+(k-1)%(i-1))%i;
int t3 ;
get_num(t3,t1,t2,i,k);
if(t1 > t2) swap(t1,t2);
int first , second;
if(t3 < t1){
first = t1-t3-1;
second = first + t2-t1-1;
}
else if(t3 < t2){
first = t2 - t3 - 1;
second = first + i-1-t2+t1;
}
else {
first = i-1-t3+t1;
second = first + t2-t1-1;
}
if(f3[i-3] < first)
f3[i] = (f3[i-3]+t3+1)%i;
else if(f3[i-3] < second)
f3[i] = (f3[i-3]+t3+2)%i;
else
f3[i] = (f3[i-3]+t3+3)%i;
}
printf("%d %d %d\n",f3[n]+1,f2[n]+1,f[n]+1);
}
return 0;
}
int debug(int u,int k,int lim){
int a[100]={0};
int i=-1,cou=0;
while(1){
for(int cnt=0;cnt<k;cnt++){
i=(i+1)%u; while(a[i]) i=(i+1)%u;
i=i%u;
}
a[i] = 1;
cou++;
if(cou==lim) return i;
}
}
其实,求倒数第2,3,完全可以和第一个一样;比如,确定2时,先确定f【2】的解,然后继续使用f[ n ] = (f[ n-1 ] +m)%n解出即可;
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<cmath>
#include<cstring>
using namespace std;
const int MAXN = 110;
int n, m;
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
scanf("%d%d", &n, &m);
int ans1 = 0, ans2, ans3;
for(int i=2; i<=n; ++i)
{
ans1 = (ans1+m) % i;
if(i==2)
{
ans2 = !ans1;
}
else if(i==3)
{
ans2 = (ans2+m) % i;
bool vis[3];
memset(vis, 0, sizeof(vis));
vis[ans1] = vis[ans2] = true;
for(int j=0; j<3; ++j)if(!vis[j])
{
ans3 = j;
break;
}
}
else
{
ans2 = (ans2+m) % i;
ans3 = (ans3+m) % i;
}
}
printf("%d %d %d\n", ans3+1, ans2+1, ans1+1);
}
return 0;
}