POJ1012-Joseph数学

题目链接:http://poj.org/problem?id=1012

题目大意:

  约瑟夫环的一个扩展,2*k个人围一圈,前k个是好人,后k个是坏人。报到m的人就要死掉,然后重新开始报数。要求的是最小的m使得后k个人总是先死掉!

题目分析:

  这道题真心很头疼的啊!约瑟夫环的问题就是很难解,而且比较难理解的啊。。

  做法很简单,就是按照原先做约瑟夫环的方法,从k+1开始枚举m,找到最小的m。

  公式是:t=(t+m-1)%(sum--);sum为当前的总人数。把所有人从0开始编号到2*k-1,这样每一次死掉的人就是第t个人(去掉上一轮出局的,从原本的那个0开始重新编号后的t号会死掉!),只要保证前k个t里面不出现小于k的数就可以了。

  在本机上打个表再提交就可以保证不超时了。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 int f[100]={0,2,7,5,30,169,441,1872,7632,1740,93313,459901,1358657,2504881};
 6 int k;
 7 int t;
 8 bool ok(int m)
 9 {
10     t=0;
11     int sum=2*k;
12     for(int i=1;i<=k;i++)
13     {
14         t=(t+m-1)%sum;
15         sum--;
16         if(t<k)
17         {
18             return 0;
19         }
20     }
21     return 1;
22 }
23 int main()
24 {
25     //freopen("text.out","w",stdout);
26   //  for(k=1;k<14;k++)
27     //{
28      //   int m=k+1;
29       //  while(ok(m++)==0)
30        // {}
31       //  cout<<m-1<<",";
32   //  }
33     while(scanf("%d",&k)!=EOF && k)
34     {
35         cout<<f[k]<<endl;
36     }
37     return 0;
38 }
POJ1012
原文地址:https://www.cnblogs.com/xiaozhuyang/p/POJ1012-Joseph.html