约瑟夫问题
Posted 哦!
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了约瑟夫问题相关的知识,希望对你有一定的参考价值。
#1296 : 数论三·约瑟夫问题
时间限制:10000ms
单点时限:1000ms
内存限制:256MB
描述
小Hi和小Ho的班级正在进行班长的选举,他们决定通过一种特殊的方式来选择班长。
首先N个候选人围成一个圈,依次编号为0..N-1。然后随机抽选一个数K,并0号候选人开始按从1到K的顺序依次报数,N-1号候选人报数之后,又再次从0开始。当有人报到K时,这个人被淘汰,从圈里出去。下一个人从1开始重新报数。
也就是说每报K个数字,都会淘汰一人。这样经过N-1轮报数之后,圈内就只剩下1个人了,这个人就作为新的班长。
举个例子,假如有5个候选人,K=3:
初始 0: 0 1 2 3 4 从0号开始报数,第1次是2号报到3 1: 0 1 - 3 4 // 0 1 2, 2号候选人淘汰 从3号开始报数,第2次是0号报到3 2: - 1 3 4 // 3 4 0, 0号候选人淘汰 从1号开始报数,第3次是4号报到3 3: 1 3 - // 1 3 4, 4号候选人淘汰 从1号开始报数,第4次是1号报到3 4: - 3 // 1 3 1, 1号候选人淘汰
对于N=5,K=3的情况,最后当选班长的人是编号为3的候选人。
小Ho:小Hi,我觉得当人数和K都确定的时候已经可以确定结果了。
小Hi:嗯,没错。
小Ho:我也想当班长,小Hi你能提前告诉我应该站在哪个位置么?
小Hi:我可以告诉你怎么去求最后一个被淘汰的位置,不过具体的值你得自己去求解。
小Ho:嗯,没问题,那么你快告诉我方法吧!
输入
第1行:1个正整数t,表示多组输入数据,1≤t≤100
第2..t+1行:每行2个正整数n,k,第i+1行表示第i组测试数据,2≤n≤1,000,000,000。2≤k≤1,000
输出
第1..t行:每行1个整数,第i行表示第i组数据的解
- 样例输入
-
2 5 3 8 3
- 样例输出
-
3 6
1 #define ll long long 2 #include<algorithm> 3 #include<iostream> 4 #include<iomanip> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cstdio> 8 #include<queue> 9 #include<ctime> 10 #include<cmath> 11 #include<stack> 12 #include<map> 13 #include<set> 14 using namespace std; 15 int gi() { 16 int res=0,f=1; 17 char ch=getchar(); 18 while((ch<‘0‘||ch>‘9‘)&&ch!=‘-‘) ch=getchar(); 19 if(ch==‘-‘) ch=getchar(),f=-1; 20 while(ch>=‘0‘&&ch<=‘9‘) res=res*10+ch-‘0‘,ch=getchar(); 21 return res*f; 22 } 23 int Joseophus(int n,int k) { 24 if(n==1) return 0; 25 if(n<k) { 26 int ret=0; 27 for(int i=2;i<=n;i++) ret = (ret+k)%i; 28 return ret; 29 } 30 int ret=Joseophus(n-n/k,k); 31 if(ret<n%k) ret=ret-n%k+n; 32 else ret=ret-n%k+((ret-n%k)/(k-1)); 33 return ret; 34 } 35 int main() {// please remember :infer other things from one fact 36 freopen("Alan.in","r",stdin); 37 freopen("Alan.out","w",stdout); 38 int t=gi(); 39 while(t--) { 40 int n=gi(),k=gi(); 41 printf("%d\n",Joseophus(n,k)); 42 } 43 return 0; 44 }
以上是关于约瑟夫问题的主要内容,如果未能解决你的问题,请参考以下文章