poj1781In Danger(约瑟夫) 问题
鏈接
之前隊內賽中的一道題目 當時怎么想也沒想到,就一直放到了今天,剛才看另一題的講解突然看到時拿這個題作為引子來講的,就仔細看了下。
參考《《具體數學》》 p7。 Josephus問題
開始是講了一個古老的故事,說J和同伴陷入險境,大家不愿做俘虜,就想了個游戲來進行自殺,每第二個人就要去死。。J覺得這樣很傻,并很快的算出了自己該在的位置,逃脫了這無聊的自殺。由此引出了這個有趣的算法。
這本書上講的很清楚, 我就大體概括一下。
可以先從10個人來看 很明顯第一次死掉的是全部的偶數, 然后是 是3 7 1 9.那么J(10) = 5;
可以猜測所有的J(n)都為奇數,因為第一輪就殺掉了全部的偶數,很明顯。。
然后再猜J(n) = n/2? 很明顯 不是。不過假如有2N個人 第一次還是殺掉所有的偶數 那么剩下了n個數,那么這n個數不就是跟之前的n同樣來處理。。,
只不過編號變成了原來的2*i -1. 所以J(20) = 2*j(10)-1 = 9; 類推 J(40) = 17 所以得出j(5*2^m) = 2^(m+1)+1;
那么奇數呢,類似可知 J(2n+1) = 2*J(n)+1;
所以歸納可得
j(1) = 1;
j(2n) = 2j(n)-1;
j(2n+1) = 2j(n)+1;
這樣是很快的,每次以減少2倍或多的速度來算,不過這可關乎J的性命,所以J還得想更快的方法才能確保他逃得過此劫。
那么繼續看 1 ?2 3 ?4 5 6 7 ?8 9 10 11 12 13 14 15 ?16
1 ? 1 3 ?1 3 5 7 ?1 3 5 7 9 11 ?13 15 17 ? 1
下面對的是J(n)的值 ,結論應該可以猜出來了,與2的冪有關。
結論:對于每一個n可以寫成n=2^m+k的形式 。那么J(2^m+k) = 2k+1;
上式是由 上上的遞歸式推出來的,書上用的歸納法,數學不好就不再證了。
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 100000 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 int main() 18 { 19 int n,m; 20 char c; 21 while(cin>>n>>c>>m) 22 { 23 if(!n&&!m) break; 24 n = n*pow(10.0,m); 25 int k = log(n*1.0)/log(2.0); 26 int s = pow(2.0,k); 27 cout<<(n-s)*2+1<<endl; 28 } 29 return 0; 30 } View Code?
轉載于:https://www.cnblogs.com/shangyu/p/3597712.html
總結
以上是生活随笔為你收集整理的poj1781In Danger(约瑟夫) 问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 分割视图控制器(UISplitViewC
- 下一篇: ZYNQ学习(1) —— 基础开发流程