要求最后一位数的话比较简单,直接 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; }