题目描述
n个人围成环,首先第m个人出列,然后从下一个开始,数到第k个就出列。问最后剩下的是谁?
输入
多组数据。每组数据包含3个整数n,k,m ( 2≤n≤10000 ,1≤k≤10000,1≤m≤n )。输入结束标志为n=k=m=0。
输出
对于每组数据,输出最后一个被删除的数。
样例输入
8 5 3
100 9999 98
10000 10000 10000
0 0 0
样例输出
1
93
2019
题解
假设将编号变为0~n-1。第一次拿数就应该是 k-1 ( 假设 k < n ) ,然后,我们从k开始重新编号,即 k -> 0 ,k+1 -> 1 ........ 。新的编号与原编号有什么关系?原编号 = (新编号+ k )% n。
可以想象,当还有最后一个人的时候,他的新编号一定是 0,即 f [ 1 ] = 0 , 他在上一轮的编号 f [ 2 ] = ( f [ 1 ] + k ) % 2,然后由 f [ 2 ] 推出 f [ 3 ] 继而 f [ n ] 就是答案。最后再考虑从m开始取编号从一开始。
#include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define ll long long const int maxn=10000+50; int n,k,m; int f[maxn]; template<typename T>void read(T& aa){ char cc; ll ff;aa=0;cc=getchar();ff=1; while((cc<'0'||cc>'9')&&cc!='-') cc=getchar(); if(cc=='-') ff=-1,cc=getchar(); while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar(); aa*=ff; } int main(){ while(scanf("%d%d%d",&n,&k,&m)&&(n||m||k)){ f[1]=0; for(int i=2;i<=n;i++) f[i]=(f[i-1]+k)%i; int ans=(m-k+1+f[n])%n; if(ans<0) ans+=n; cout<<ans<<endl; } return 0; }